Merge "[pm] change internal flags to long"
diff --git a/Android.bp b/Android.bp
index 241c418..778aa55 100644
--- a/Android.bp
+++ b/Android.bp
@@ -82,6 +82,7 @@
         ":framework-mca-filterpacks-sources",
         ":framework-media-sources",
         ":framework-mms-sources",
+        ":framework-omapi-sources",
         ":framework-opengl-sources",
         ":framework-rs-sources",
         ":framework-sax-sources",
@@ -154,6 +155,7 @@
         "framework-scheduling.stubs.module_lib",
         "framework-sdkextensions.stubs.module_lib",
         "framework-statsd.stubs.module_lib",
+        "framework-supplementalprocess.stubs.module_lib",
         "framework-tethering.stubs.module_lib",
         "framework-uwb.stubs.module_lib",
         "framework-wifi.stubs.module_lib",
@@ -177,6 +179,7 @@
         "framework-scheduling.impl",
         "framework-sdkextensions.impl",
         "framework-statsd.impl",
+        "framework-supplementalprocess.impl",
         "framework-tethering.impl",
         "framework-uwb.impl",
         "framework-wifi.impl",
@@ -271,6 +274,7 @@
         "android.hardware.vibrator-V1.2-java",
         "android.hardware.vibrator-V1.3-java",
         "android.hardware.vibrator-V2-java",
+        "android.se.omapi-V1-java",
         "android.system.suspend.control.internal-java",
         "devicepolicyprotosnano",
 
@@ -322,8 +326,12 @@
         "error_prone_android_framework",
     ],
     required: [
+        // TODO(b/120066492): remove default_television.xml when the build system
+        // propagates "required" properly.
+        "default_television.xml",
         "framework-platform-compat-config",
-        // TODO: remove gps_debug and protolog.conf.json when the build system propagates "required" properly.
+        // TODO(b/120066492): remove gps_debug and protolog.conf.json when the build
+        // system propagates "required" properly.
         "gps_debug.conf",
         "icu4j-platform-compat-config",
         "protolog.conf.json.gz",
@@ -331,6 +339,7 @@
         "TeleService-platform-compat-config",
         "documents-ui-compat-config",
         "calendar-provider-compat-config",
+        "contacts-provider-platform-compat-config",
     ],
     libs: [
         "app-compat-annotations",
@@ -375,6 +384,9 @@
         "//frameworks/base/packages/Tethering/tests/unit",
         "//packages/modules/Connectivity/Tethering/tests/unit",
     ],
+    lint: {
+        extra_check_modules: ["AndroidFrameworkLintChecker"],
+    },
     errorprone: {
         javacflags: [
             "-Xep:AndroidFrameworkBinderIdentity:ERROR",
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 31f7f6e..7a4ef2a 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -126,6 +126,7 @@
         ":framework-scheduling-sources",
         ":framework-sdkextensions-sources",
         ":framework-statsd-sources",
+        ":framework-supplementalprocess-sources",
         ":framework-tethering-srcs",
         ":framework-uwb-updatable-sources",
         ":framework-wifi-updatable-sources",
@@ -172,6 +173,7 @@
         ":framework-scheduling{.public.stubs.source}",
         ":framework-sdkextensions{.public.stubs.source}",
         ":framework-statsd{.public.stubs.source}",
+        ":framework-supplementalprocess{.public.stubs.source}",
         ":framework-tethering{.public.stubs.source}",
         ":framework-uwb{.public.stubs.source}",
         ":framework-wifi{.public.stubs.source}",
@@ -211,6 +213,7 @@
         ":framework-scheduling{.public.annotations.zip}",
         ":framework-sdkextensions{.public.annotations.zip}",
         ":framework-statsd{.public.annotations.zip}",
+        ":framework-supplementalprocess{.public.annotations.zip}",
         ":framework-tethering{.public.annotations.zip}",
         ":framework-uwb{.public.annotations.zip}",
         ":framework-wifi{.public.annotations.zip}",
diff --git a/GAME_MANAGER_OWNERS b/GAME_MANAGER_OWNERS
new file mode 100644
index 0000000..502a9e36
--- /dev/null
+++ b/GAME_MANAGER_OWNERS
@@ -0,0 +1,2 @@
+lpy@google.com
+timvp@google.com
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 3f94c89..3b11036 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -250,6 +250,7 @@
     "framework-scheduling.stubs",
     "framework-sdkextensions.stubs",
     "framework-statsd.stubs",
+    "framework-supplementalprocess.stubs",
     "framework-tethering.stubs",
     "framework-uwb.stubs",
     "framework-wifi.stubs",
@@ -271,6 +272,7 @@
     "framework-scheduling.stubs.system",
     "framework-sdkextensions.stubs.system",
     "framework-statsd.stubs.system",
+    "framework-supplementalprocess.stubs",
     "framework-tethering.stubs.system",
     "framework-uwb.stubs.system",
     "framework-wifi.stubs.system",
diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
index 8a6c60f..1cd5d96 100644
--- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
@@ -138,6 +138,21 @@
     }
 
     @Test
+    public void testCreate_RandomText_NoStyled_Balanced_Hyphenation_Fast() {
+        final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            state.pauseTiming();
+            final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
+            state.resumeTiming();
+
+            StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
+                    .setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL_FAST)
+                    .setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
+                    .build();
+        }
+    }
+
+    @Test
     public void testCreate_RandomText_Styled_Greedy_NoHyphenation() {
         final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
         while (state.keepRunning()) {
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 392df73..1620983 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -5142,7 +5142,7 @@
                 Slog.d(TAG, "mBroadcastRefCount -> " + mBroadcastRefCount);
             }
             if (mBroadcastRefCount == 0) {
-                mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0).sendToTarget();
+                mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 0, 0).sendToTarget();
                 mWakeLock.release();
                 if (mInFlight.size() > 0) {
                     mLog.w("Finished all dispatches with " + mInFlight.size()
@@ -5314,7 +5314,7 @@
             if (mBroadcastRefCount == 0) {
                 setWakelockWorkSource(alarm.workSource, alarm.creatorUid, alarm.statsTag, true);
                 mWakeLock.acquire();
-                mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1).sendToTarget();
+                mHandler.obtainMessage(AlarmHandler.REPORT_ALARMS_ACTIVE, 1, 0).sendToTarget();
             }
             final InFlight inflight = new InFlight(AlarmManagerService.this, alarm, nowELAPSED);
             mInFlight.add(inflight);
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/TareBill.java b/apex/jobscheduler/service/java/com/android/server/alarm/TareBill.java
index e2f5ee1..a348136 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/TareBill.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/TareBill.java
@@ -37,7 +37,7 @@
 import java.util.List;
 
 /**
- * Container to maintain alarm TARE {@link ActionBill}s and their related methods.
+ * Container to maintain alarm TARE {@link ActionBill ActionBills} and their related methods.
  */
 final class TareBill {
     /**
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 714c90b..3da508d 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1371,7 +1371,11 @@
                     jobStatus.hasContentTriggerConstraint(),
                     jobStatus.isRequestedExpeditedJob(),
                     /* isRunningAsExpeditedJob */ false,
-                    JobProtoEnums.STOP_REASON_UNDEFINED);
+                    JobProtoEnums.STOP_REASON_UNDEFINED,
+                    jobStatus.getJob().isPrefetch(),
+                    jobStatus.getJob().getPriority(),
+                    jobStatus.getEffectivePriority(),
+                    jobStatus.getNumFailures());
 
             // If the job is immediately ready to run, then we can just immediately
             // put it in the pending list and try to schedule it.  This is especially
@@ -2299,7 +2303,7 @@
     }
 
     /**
-     * Check if a job is restricted by any of the declared {@link JobRestriction}s.
+     * Check if a job is restricted by any of the declared {@link JobRestriction JobRestrictions}.
      * Note, that the jobs with {@link JobInfo#BIAS_FOREGROUND_SERVICE} bias or higher may not
      * be restricted, thus we won't even perform the check, but simply return null early.
      *
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index b44178f..9cae8645 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -356,7 +356,11 @@
                     job.hasContentTriggerConstraint(),
                     job.isRequestedExpeditedJob(),
                     job.shouldTreatAsExpeditedJob(),
-                    JobProtoEnums.STOP_REASON_UNDEFINED);
+                    JobProtoEnums.STOP_REASON_UNDEFINED,
+                    job.getJob().isPrefetch(),
+                    job.getJob().getPriority(),
+                    job.getEffectivePriority(),
+                    job.getNumFailures());
             try {
                 mBatteryStats.noteJobStart(job.getBatteryName(), job.getSourceUid());
             } catch (RemoteException e) {
@@ -1028,7 +1032,11 @@
                 completedJob.hasContentTriggerConstraint(),
                 completedJob.isRequestedExpeditedJob(),
                 completedJob.startedAsExpeditedJob,
-                mParams.getStopReason());
+                mParams.getStopReason(),
+                completedJob.getJob().isPrefetch(),
+                completedJob.getJob().getPriority(),
+                completedJob.getEffectivePriority(),
+                completedJob.getNumFailures());
         try {
             mBatteryStats.noteJobFinish(mRunningJob.getBatteryName(), mRunningJob.getSourceUid(),
                     internalStopReason);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING
index 7d12b95..d9c4632 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING
+++ b/apex/jobscheduler/service/java/com/android/server/job/TEST_MAPPING
@@ -50,6 +50,12 @@
                 {"include-filter": "com.android.cts.net.HostsideRestrictBackgroundNetworkTests#testMeteredNetworkAccess_expeditedJob"},
                 {"include-filter": "com.android.cts.net.HostsideRestrictBackgroundNetworkTests#testNonMeteredNetworkAccess_expeditedJob"}
             ]
+        },
+        {
+            "name": "CtsStatsdAtomHostTestCases",
+            "options": [
+                {"include-filter": "android.cts.statsdatom.jobscheduler"}
+            ]
         }
     ]
 }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
index 393f368..9749c80 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/PrefetchController.java
@@ -25,8 +25,10 @@
 import android.annotation.CurrentTimeMillisLong;
 import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
+import android.app.job.JobInfo;
 import android.app.usage.UsageStatsManagerInternal;
 import android.app.usage.UsageStatsManagerInternal.EstimatedLaunchTimeChangedListener;
+import android.appwidget.AppWidgetManager;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
@@ -38,6 +40,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseArrayMap;
+import android.util.SparseBooleanArray;
 import android.util.TimeUtils;
 
 import com.android.internal.annotations.GuardedBy;
@@ -61,6 +64,13 @@
     private final PcConstants mPcConstants;
     private final PcHandler mHandler;
 
+    // Note: when determining prefetch bit satisfaction, we mark the bit as satisfied for apps with
+    // active widgets assuming that any prefetch jobs are being used for the widget. However, we
+    // don't have a callback telling us when widget status changes, which is incongruent with the
+    // aforementioned assumption. This inconsistency _should_ be fine since any jobs scheduled
+    // before the widget is activated are definitely not for the widget and don't have to be updated
+    // to "satisfied=true".
+    private AppWidgetManager mAppWidgetManager;
     private final UsageStatsManagerInternal mUsageStatsManagerInternal;
 
     @GuardedBy("mLock")
@@ -71,6 +81,9 @@
      */
     @GuardedBy("mLock")
     private final SparseArrayMap<String, Long> mEstimatedLaunchTimes = new SparseArrayMap<>();
+    /** Cached list of UIDs in the TOP state. */
+    @GuardedBy("mLock")
+    private final SparseBooleanArray mTopUids = new SparseBooleanArray();
     private final ThresholdAlarmListener mThresholdAlarmListener;
 
     /**
@@ -98,6 +111,7 @@
 
     private static final int MSG_RETRIEVE_ESTIMATED_LAUNCH_TIME = 0;
     private static final int MSG_PROCESS_UPDATED_ESTIMATED_LAUNCH_TIME = 1;
+    private static final int MSG_PROCESS_TOP_STATE_CHANGE = 2;
 
     public PrefetchController(JobSchedulerService service) {
         super(service);
@@ -112,6 +126,11 @@
     }
 
     @Override
+    public void onSystemServicesReady() {
+        mAppWidgetManager = mContext.getSystemService(AppWidgetManager.class);
+    }
+
+    @Override
     @GuardedBy("mLock")
     public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
         if (jobStatus.getJob().isPrefetch()) {
@@ -165,6 +184,22 @@
         mThresholdAlarmListener.removeAlarmsForUserId(userId);
     }
 
+    @GuardedBy("mLock")
+    @Override
+    public void onUidBiasChangedLocked(int uid, int newBias) {
+        final boolean isNowTop = newBias == JobInfo.BIAS_TOP_APP;
+        final boolean wasTop = mTopUids.get(uid);
+        if (isNowTop) {
+            mTopUids.put(uid, true);
+        } else {
+            // Delete entries of non-top apps so the set doesn't get too large.
+            mTopUids.delete(uid);
+        }
+        if (isNowTop != wasTop) {
+            mHandler.obtainMessage(MSG_PROCESS_TOP_STATE_CHANGE, uid, 0).sendToTarget();
+        }
+    }
+
     /** Return the app's next estimated launch time. */
     @GuardedBy("mLock")
     @CurrentTimeMillisLong
@@ -205,6 +240,35 @@
         return changed;
     }
 
+    private void maybeUpdateConstraintForUid(int uid) {
+        synchronized (mLock) {
+            final ArraySet<String> pkgs = mService.getPackagesForUidLocked(uid);
+            if (pkgs == null) {
+                return;
+            }
+            final int userId = UserHandle.getUserId(uid);
+            final ArraySet<JobStatus> changedJobs = new ArraySet<>();
+            final long now = sSystemClock.millis();
+            final long nowElapsed = sElapsedRealtimeClock.millis();
+            for (int p = pkgs.size() - 1; p >= 0; --p) {
+                final String pkgName = pkgs.valueAt(p);
+                final ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, pkgName);
+                if (jobs == null) {
+                    continue;
+                }
+                for (int i = 0; i < jobs.size(); i++) {
+                    final JobStatus js = jobs.valueAt(i);
+                    if (updateConstraintLocked(js, now, nowElapsed)) {
+                        changedJobs.add(js);
+                    }
+                }
+            }
+            if (changedJobs.size() > 0) {
+                mStateChangedListener.onControllerStateChanged(changedJobs);
+            }
+        }
+    }
+
     private void processUpdatedEstimatedLaunchTime(int userId, @NonNull String pkgName,
             @CurrentTimeMillisLong long newEstimatedLaunchTime) {
         if (DEBUG) {
@@ -244,9 +308,30 @@
     @GuardedBy("mLock")
     private boolean updateConstraintLocked(@NonNull JobStatus jobStatus,
             @CurrentTimeMillisLong long now, @ElapsedRealtimeLong long nowElapsed) {
-        return jobStatus.setPrefetchConstraintSatisfied(nowElapsed,
-                willBeLaunchedSoonLocked(
-                        jobStatus.getSourceUserId(), jobStatus.getSourcePackageName(), now));
+        // Mark a prefetch constraint as satisfied in the following scenarios:
+        //   1. The app is not open but it will be launched soon
+        //   2. The app is open and the job is already running (so we let it finish)
+        //   3. The app is not open but has an active widget (we can't tell if a widget displays
+        //      status/data, so this assumes the prefetch job is to update the data displayed on
+        //      the widget).
+        final boolean appIsOpen = mTopUids.get(jobStatus.getSourceUid());
+        final boolean satisfied;
+        if (!appIsOpen) {
+            final int userId = jobStatus.getSourceUserId();
+            final String pkgName = jobStatus.getSourcePackageName();
+            satisfied = willBeLaunchedSoonLocked(userId, pkgName, now)
+                    // At the time of implementation, isBoundWidgetPackage() results in a process ID
+                    // check and then a lookup into a map. Calling the method here every time
+                    // is based on the assumption that widgets won't change often and
+                    // AppWidgetManager won't be a bottleneck, so having a local cache won't provide
+                    // huge performance gains. If anything changes, we should reconsider having a
+                    // local cache.
+                    || (mAppWidgetManager != null
+                            && mAppWidgetManager.isBoundWidgetPackage(pkgName, userId));
+        } else {
+            satisfied = mService.isCurrentlyRunningLocked(jobStatus);
+        }
+        return jobStatus.setPrefetchConstraintSatisfied(nowElapsed, satisfied);
     }
 
     @GuardedBy("mLock")
@@ -399,6 +484,11 @@
                     processUpdatedEstimatedLaunchTime(args.argi1, (String) args.arg1, args.argl1);
                     args.recycle();
                     break;
+
+                case MSG_PROCESS_TOP_STATE_CHANGE:
+                    final int uid = msg.arg1;
+                    maybeUpdateConstraintForUid(uid);
+                    break;
             }
         }
     }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 29c1108..c147ef8 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -148,8 +148,9 @@
         public int bgJobCountInMaxPeriod;
 
         /**
-         * The number of {@link TimingSession}s within the bucket window size. This will include
-         * sessions that started before the window as long as they end within the window.
+         * The number of {@link TimingSession TimingSessions} within the bucket window size.
+         * This will include sessions that started before the window as long as they end within
+         * the window.
          */
         public int sessionCountInWindow;
 
@@ -183,7 +184,7 @@
         public long sessionRateLimitExpirationTimeElapsed;
 
         /**
-         * The number of {@link TimingSession}s that ran in at least the last
+         * The number of {@link TimingSession TimingSessions} that ran in at least the last
          * {@link #mRateLimitingWindowMs}. It may contain a few stale entries since cleanup won't
          * happen exactly every {@link #mRateLimitingWindowMs}. This should only be considered
          * valid before elapsed realtime has reached {@link #sessionRateLimitExpirationTimeElapsed}.
@@ -363,8 +364,8 @@
             QcConstants.DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
 
     /**
-     * The maximum number of {@link TimingSession}s that can run within the past {@link
-     * #mRateLimitingWindowMs}.
+     * The maximum number of {@link TimingSession TimingSessions} that can run within the past
+     * {@link #mRateLimitingWindowMs}.
      */
     private int mMaxSessionCountPerRateLimitingWindow =
             QcConstants.DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW;
@@ -434,9 +435,10 @@
     };
 
     /**
-     * The maximum number of {@link TimingSession}s based on its standby bucket. For each max value
-     * count in the array, the app will not be allowed to have more than that many number of
-     * {@link TimingSession}s within the latest time interval of its rolling window size.
+     * The maximum number of {@link TimingSession TimingSessions} based on its standby bucket.
+     * For each max value count in the array, the app will not be allowed to have more than that
+     * many number of {@link TimingSession TimingSessions} within the latest time interval of its
+     * rolling window size.
      *
      * @see #mBucketPeriodsMs
      */
@@ -450,8 +452,8 @@
     };
 
     /**
-     * Treat two distinct {@link TimingSession}s as the same if they start and end within this
-     * amount of time of each other.
+     * Treat two distinct {@link TimingSession TimingSessions} as the same if they start and end
+     * within this amount of time of each other.
      */
     private long mTimingSessionCoalescingDurationMs =
             QcConstants.DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS;
@@ -997,8 +999,8 @@
     /**
      * Returns the amount of time, in milliseconds, until the package would have reached its
      * duration quota, assuming it has a job counting towards its quota the entire time. This takes
-     * into account any {@link TimingSession}s that may roll out of the window as the job is
-     * running.
+     * into account any {@link TimingSession TimingSessions} that may roll out of the window as the
+     * job is running.
      */
     @VisibleForTesting
     long getTimeUntilQuotaConsumedLocked(final int userId, @NonNull final String packageName) {
@@ -2010,9 +2012,8 @@
             if (DEBUG) {
                 Slog.v(TAG, "Starting to track " + jobStatus.toShortString());
             }
-            // Always track jobs, even when charging.
-            mRunningBgJobs.add(jobStatus);
-            if (shouldTrackLocked()) {
+            // Always maintain list of running jobs, even when quota is free.
+            if (mRunningBgJobs.add(jobStatus) && shouldTrackLocked()) {
                 mBgJobCount++;
                 if (mRegularJobTimer) {
                     incrementJobCountLocked(mPkg.userId, mPkg.packageName, 1);
@@ -3073,45 +3074,45 @@
                 DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
 
         /**
-         * The maximum number of {@link TimingSession}s an app can run within this particular
-         * standby bucket's window size.
+         * The maximum number of {@link TimingSession TimingSessions} an app can run within this
+         * particular standby bucket's window size.
          */
         public int MAX_SESSION_COUNT_ACTIVE = DEFAULT_MAX_SESSION_COUNT_ACTIVE;
 
         /**
-         * The maximum number of {@link TimingSession}s an app can run within this particular
-         * standby bucket's window size.
+         * The maximum number of {@link TimingSession TimingSessions} an app can run within this
+         * particular standby bucket's window size.
          */
         public int MAX_SESSION_COUNT_WORKING = DEFAULT_MAX_SESSION_COUNT_WORKING;
 
         /**
-         * The maximum number of {@link TimingSession}s an app can run within this particular
-         * standby bucket's window size.
+         * The maximum number of {@link TimingSession TimingSessions} an app can run within this
+         * particular standby bucket's window size.
          */
         public int MAX_SESSION_COUNT_FREQUENT = DEFAULT_MAX_SESSION_COUNT_FREQUENT;
 
         /**
-         * The maximum number of {@link TimingSession}s an app can run within this particular
-         * standby bucket's window size.
+         * The maximum number of {@link TimingSession TimingSessions} an app can run within this
+         * particular standby bucket's window size.
          */
         public int MAX_SESSION_COUNT_RARE = DEFAULT_MAX_SESSION_COUNT_RARE;
 
         /**
-         * The maximum number of {@link TimingSession}s an app can run within this particular
-         * standby bucket's window size.
+         * The maximum number of {@link TimingSession TimingSessions} an app can run within this
+         * particular standby bucket's window size.
          */
         public int MAX_SESSION_COUNT_RESTRICTED = DEFAULT_MAX_SESSION_COUNT_RESTRICTED;
 
         /**
-         * The maximum number of {@link TimingSession}s that can run within the past
+         * The maximum number of {@link TimingSession TimingSessions} that can run within the past
          * {@link #ALLOWED_TIME_PER_PERIOD_MS}.
          */
         public int MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW =
                 DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW;
 
         /**
-         * Treat two distinct {@link TimingSession}s as the same if they start and end within this
-         * amount of time of each other.
+         * Treat two distinct {@link TimingSession TimingSessions} as the same if they start and
+         * end within this amount of time of each other.
          */
         public long TIMING_SESSION_COALESCING_DURATION_MS =
                 DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS;
@@ -3125,8 +3126,8 @@
         private static final int MIN_BUCKET_JOB_COUNT = 10;
 
         /**
-         * The minimum number of {@link TimingSession}s that any bucket will be allowed to run
-         * within its window.
+         * The minimum number of {@link TimingSession TimingSessions} that any bucket will be
+         * allowed to run within its window.
          */
         private static final int MIN_BUCKET_SESSION_COUNT = 1;
 
diff --git a/apex/jobscheduler/service/java/com/android/server/job/restrictions/JobRestriction.java b/apex/jobscheduler/service/java/com/android/server/job/restrictions/JobRestriction.java
index 3387b1d..4067541 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/restrictions/JobRestriction.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/restrictions/JobRestriction.java
@@ -54,7 +54,8 @@
 
     /**
      * Called by {@link JobSchedulerService} to check if it may proceed with scheduling the job (in
-     * case all constraints are satisfied and all other {@link JobRestriction}s are fine with it)
+     * case all constraints are satisfied and all other {@link JobRestriction JobRestrictions} are
+     * fine with it).
      *
      * @param job to be checked
      * @return false if the {@link JobSchedulerService} should not schedule this job at the moment,
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
index c5f0f32..005c447 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
@@ -85,7 +85,7 @@
             mCurrentOngoingEvents = new SparseArrayMap<>();
 
     /**
-     * Set of {@link ActionAffordabilityNote}s keyed by userId-pkgName.
+     * Set of {@link ActionAffordabilityNote ActionAffordabilityNotes} keyed by userId-pkgName.
      *
      * Note: it would be nice/better to sort by base price since that doesn't change and simply
      * look at the change in the "insertion" of what would be affordable, but since CTP
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
index 630f1e7..0fa0c47 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
@@ -74,7 +74,7 @@
     }
 
     /**
-     * A collection of {@link AnticipatedAction}s that will be performed together.
+     * A collection of {@link AnticipatedAction AnticipatedActions} that will be performed together.
      */
     final class ActionBill {
         private static final Comparator<AnticipatedAction>
diff --git a/apex/media/framework/java/android/media/MediaTranscodingManager.java b/apex/media/framework/java/android/media/MediaTranscodingManager.java
index 3bfffbcd..aff3204 100644
--- a/apex/media/framework/java/android/media/MediaTranscodingManager.java
+++ b/apex/media/framework/java/android/media/MediaTranscodingManager.java
@@ -949,6 +949,8 @@
              *
              * @return the video track format to be used if transcoding should be performed,
              *         and null otherwise.
+             * @throws IllegalArgumentException if the hinted source video format contains invalid
+             *         parameters.
              */
             @Nullable
             public MediaFormat resolveVideoFormat() {
@@ -959,20 +961,19 @@
                 MediaFormat videoTrackFormat = new MediaFormat(mSrcVideoFormatHint);
                 videoTrackFormat.setString(MediaFormat.KEY_MIME, MediaFormat.MIMETYPE_VIDEO_AVC);
 
-                int width = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_WIDTH);
-                int height = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_HEIGHT);
+                int width = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_WIDTH, -1);
+                int height = mSrcVideoFormatHint.getInteger(MediaFormat.KEY_HEIGHT, -1);
                 if (width <= 0 || height <= 0) {
                     throw new IllegalArgumentException(
                             "Source Width and height must be larger than 0");
                 }
 
-                float frameRate = 30.0f; // default to 30fps.
-                if (mSrcVideoFormatHint.containsKey(MediaFormat.KEY_FRAME_RATE)) {
-                    frameRate = mSrcVideoFormatHint.getFloat(MediaFormat.KEY_FRAME_RATE);
-                    if (frameRate <= 0) {
-                        throw new IllegalArgumentException(
-                                "frameRate must be larger than 0");
-                    }
+                float frameRate =
+                        mSrcVideoFormatHint.getNumber(MediaFormat.KEY_FRAME_RATE, 30.0)
+                        .floatValue();
+                if (frameRate <= 0) {
+                    throw new IllegalArgumentException(
+                            "frameRate must be larger than 0");
                 }
 
                 int bitrate = getAVCBitrate(width, height, frameRate);
diff --git a/api/Android.bp b/api/Android.bp
index 1bc50bd..1ec1b3c 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -106,6 +106,7 @@
         ":framework-scheduling{.public.api.txt}",
         ":framework-sdkextensions{.public.api.txt}",
         ":framework-statsd{.public.api.txt}",
+        ":framework-supplementalprocess{.public.api.txt}",
         ":framework-tethering{.public.api.txt}",
         ":framework-uwb{.public.api.txt}",
         ":framework-wifi{.public.api.txt}",
@@ -167,6 +168,7 @@
         ":framework-scheduling{.public.stubs.source}",
         ":framework-sdkextensions{.public.stubs.source}",
         ":framework-statsd{.public.stubs.source}",
+        ":framework-supplementalprocess{.public.stubs.source}",
         ":framework-tethering{.public.stubs.source}",
         ":framework-uwb{.public.stubs.source}",
         ":framework-wifi{.public.stubs.source}",
@@ -195,6 +197,7 @@
         ":framework-scheduling{.public.removed-api.txt}",
         ":framework-sdkextensions{.public.removed-api.txt}",
         ":framework-statsd{.public.removed-api.txt}",
+        ":framework-supplementalprocess{.public.removed-api.txt}",
         ":framework-tethering{.public.removed-api.txt}",
         ":framework-uwb{.public.removed-api.txt}",
         ":framework-wifi{.public.removed-api.txt}",
@@ -237,6 +240,7 @@
         ":framework-scheduling{.system.api.txt}",
         ":framework-sdkextensions{.system.api.txt}",
         ":framework-statsd{.system.api.txt}",
+        ":framework-supplementalprocess{.system.api.txt}",
         ":framework-tethering{.system.api.txt}",
         ":framework-uwb{.system.api.txt}",
         ":framework-wifi{.system.api.txt}",
@@ -297,6 +301,7 @@
         ":framework-scheduling{.system.removed-api.txt}",
         ":framework-sdkextensions{.system.removed-api.txt}",
         ":framework-statsd{.system.removed-api.txt}",
+        ":framework-supplementalprocess{.system.removed-api.txt}",
         ":framework-tethering{.system.removed-api.txt}",
         ":framework-uwb{.system.removed-api.txt}",
         ":framework-wifi{.system.removed-api.txt}",
@@ -339,6 +344,7 @@
         ":framework-scheduling{.module-lib.api.txt}",
         ":framework-sdkextensions{.module-lib.api.txt}",
         ":framework-statsd{.module-lib.api.txt}",
+        ":framework-supplementalprocess{.module-lib.api.txt}",
         ":framework-tethering{.module-lib.api.txt}",
         ":framework-uwb{.module-lib.api.txt}",
         ":framework-wifi{.module-lib.api.txt}",
@@ -401,6 +407,7 @@
         ":framework-scheduling{.module-lib.removed-api.txt}",
         ":framework-sdkextensions{.module-lib.removed-api.txt}",
         ":framework-statsd{.module-lib.removed-api.txt}",
+        ":framework-supplementalprocess{.module-lib.removed-api.txt}",
         ":framework-tethering{.module-lib.removed-api.txt}",
         ":framework-uwb{.module-lib.removed-api.txt}",
         ":framework-wifi{.module-lib.removed-api.txt}",
@@ -521,6 +528,7 @@
         ":framework-scheduling.stubs{.jar}",
         ":framework-sdkextensions.stubs{.jar}",
         ":framework-statsd.stubs{.jar}",
+        ":framework-supplementalprocess.stubs{.jar}",
         ":framework-tethering.stubs{.jar}",
         ":framework-uwb.stubs{.jar}",
         ":framework-wifi.stubs{.jar}",
diff --git a/boot/Android.bp b/boot/Android.bp
index d88e839..3273f2c 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -96,6 +96,10 @@
             module: "com.android.sdkext-bootclasspath-fragment",
         },
         {
+            apex: "com.android.supplementalprocess",
+            module: "com.android.supplementalprocess-bootclasspath-fragment",
+        },
+        {
             apex: "com.android.tethering",
             module: "com.android.tethering-bootclasspath-fragment",
         },
diff --git a/boot/boot-image-profile.txt b/boot/boot-image-profile.txt
index 5f27cc7..82269d4 100644
--- a/boot/boot-image-profile.txt
+++ b/boot/boot-image-profile.txt
@@ -2899,10 +2899,8 @@
 HSPLandroid/app/assist/AssistStructure$ViewNode;->getChildCount()I
 HSPLandroid/app/assist/AssistStructure$ViewNode;->writeSelfToParcel(Landroid/os/Parcel;Landroid/os/PooledStringWriter;Z[FZ)I+]Landroid/view/autofill/AutofillId;Landroid/view/autofill/AutofillId;]Landroid/graphics/Matrix;Landroid/graphics/Matrix;]Landroid/app/assist/AssistStructure$ViewNodeText;Landroid/app/assist/AssistStructure$ViewNodeText;]Landroid/os/Parcel;Landroid/os/Parcel;
 HSPLandroid/app/assist/AssistStructure$ViewNode;->writeString(Landroid/os/Parcel;Landroid/os/PooledStringWriter;Ljava/lang/String;)V+]Landroid/os/PooledStringWriter;Landroid/os/PooledStringWriter;]Landroid/os/Parcel;Landroid/os/Parcel;
-HSPLandroid/app/assist/AssistStructure$ViewNodeBuilder;-><init>()V
 HSPLandroid/app/assist/AssistStructure$ViewNodeBuilder;->getChildCount()I
 HSPLandroid/app/assist/AssistStructure$ViewNodeBuilder;->getNodeText()Landroid/app/assist/AssistStructure$ViewNodeText;
-HSPLandroid/app/assist/AssistStructure$ViewNodeBuilder;->getViewNode()Landroid/app/assist/AssistStructure$ViewNode;
 HSPLandroid/app/assist/AssistStructure$ViewNodeBuilder;->newChild(I)Landroid/view/ViewStructure;
 HSPLandroid/app/assist/AssistStructure$ViewNodeBuilder;->setAutofillHints([Ljava/lang/String;)V
 HSPLandroid/app/assist/AssistStructure$ViewNodeBuilder;->setAutofillId(Landroid/view/autofill/AutofillId;)V
@@ -3883,8 +3881,6 @@
 HSPLandroid/content/ContentResolver$ResultListener;-><init>(Landroid/content/ContentResolver$1;)V
 HSPLandroid/content/ContentResolver$ResultListener;->onResult(Landroid/os/Bundle;)V+]Landroid/os/ParcelableException;Landroid/os/ParcelableException;]Ljava/lang/Object;Landroid/content/ContentResolver$StringResultListener;,Landroid/content/ContentResolver$UriResultListener;]Landroid/os/Bundle;Landroid/os/Bundle;]Landroid/content/ContentResolver$ResultListener;Landroid/content/ContentResolver$UriResultListener;,Landroid/content/ContentResolver$StringResultListener;
 HSPLandroid/content/ContentResolver$ResultListener;->waitForResult(J)V+]Ljava/lang/Object;Landroid/content/ContentResolver$StringResultListener;
-HSPLandroid/content/ContentResolver$StringResultListener;-><init>()V
-HSPLandroid/content/ContentResolver$StringResultListener;-><init>(Landroid/content/ContentResolver$1;)V
 HSPLandroid/content/ContentResolver$StringResultListener;->getResultFromBundle(Landroid/os/Bundle;)Ljava/lang/Object;+]Landroid/content/ContentResolver$StringResultListener;Landroid/content/ContentResolver$StringResultListener;
 HSPLandroid/content/ContentResolver$StringResultListener;->getResultFromBundle(Landroid/os/Bundle;)Ljava/lang/String;+]Landroid/os/Bundle;Landroid/os/Bundle;
 HSPLandroid/content/ContentResolver;-><init>(Landroid/content/Context;)V
@@ -7029,7 +7025,6 @@
 HSPLandroid/graphics/Region$1;->createFromParcel(Landroid/os/Parcel;)Landroid/graphics/Region;
 HSPLandroid/graphics/Region$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;+]Landroid/graphics/Region$1;Landroid/graphics/Region$1;
 HSPLandroid/graphics/Region;-><init>()V
-HSPLandroid/graphics/Region;-><init>(IIII)V
 HSPLandroid/graphics/Region;-><init>(J)V
 HSPLandroid/graphics/Region;->access$000(Landroid/os/Parcel;)J
 HSPLandroid/graphics/Region;->equals(Ljava/lang/Object;)Z
@@ -7075,7 +7070,6 @@
 HSPLandroid/graphics/RenderNode;->hasDisplayList()Z
 HSPLandroid/graphics/RenderNode;->hasIdentityMatrix()Z
 HSPLandroid/graphics/RenderNode;->isAttached()Z+]Landroid/graphics/RenderNode$AnimationHost;Landroid/view/ViewAnimationHostBridge;
-HSPLandroid/graphics/RenderNode;->isPivotExplicitlySet()Z
 HSPLandroid/graphics/RenderNode;->offsetTopAndBottom(I)Z
 HSPLandroid/graphics/RenderNode;->setAlpha(F)Z
 HSPLandroid/graphics/RenderNode;->setAnimationMatrix(Landroid/graphics/Matrix;)Z+]Landroid/graphics/Matrix;Landroid/graphics/Matrix;
@@ -8283,7 +8277,6 @@
 HSPLandroid/hardware/GeomagneticField$LegendreTable;-><init>(IF)V
 HSPLandroid/hardware/GeomagneticField;-><init>(FFFJ)V
 HSPLandroid/hardware/GeomagneticField;->computeGeocentricCoordinates(FFF)V
-HSPLandroid/hardware/GeomagneticField;->getDeclination()F
 HSPLandroid/hardware/HardwareBuffer$1;->createFromParcel(Landroid/os/Parcel;)Landroid/hardware/HardwareBuffer;
 HSPLandroid/hardware/HardwareBuffer$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
 HSPLandroid/hardware/HardwareBuffer;-><init>(J)V+]Llibcore/util/NativeAllocationRegistry;Llibcore/util/NativeAllocationRegistry;]Ljava/lang/Class;Ljava/lang/Class;]Ldalvik/system/CloseGuard;Ldalvik/system/CloseGuard;
@@ -11353,7 +11346,6 @@
 HSPLandroid/media/SoundPool$EventHandler;->handleMessage(Landroid/os/Message;)V
 HSPLandroid/media/SoundPool;-><init>(ILandroid/media/AudioAttributes;)V
 HSPLandroid/media/SoundPool;-><init>(ILandroid/media/AudioAttributes;Landroid/media/SoundPool$1;)V
-HSPLandroid/media/SoundPool;->load(Ljava/lang/String;I)I
 HSPLandroid/media/SoundPool;->postEventFromNative(Ljava/lang/Object;IIILjava/lang/Object;)V
 HSPLandroid/media/SoundPool;->setOnLoadCompleteListener(Landroid/media/SoundPool$OnLoadCompleteListener;)V
 HSPLandroid/media/SubtitleController$1;->handleMessage(Landroid/os/Message;)Z
@@ -11389,10 +11381,8 @@
 HSPLandroid/media/Utils;->sortDistinctRanges([Landroid/util/Range;)V
 HSPLandroid/media/audiofx/AudioEffect$Descriptor;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
 HSPLandroid/media/audiopolicy/AudioProductStrategy$AudioAttributesGroup;-><init>(II[Landroid/media/AudioAttributes;)V
-HSPLandroid/media/audiopolicy/AudioProductStrategy$AudioAttributesGroup;->supportsStreamType(I)Z
 HSPLandroid/media/audiopolicy/AudioProductStrategy;-><init>(Ljava/lang/String;I[Landroid/media/audiopolicy/AudioProductStrategy$AudioAttributesGroup;)V
 HSPLandroid/media/audiopolicy/AudioProductStrategy;->attributesMatches(Landroid/media/AudioAttributes;Landroid/media/AudioAttributes;)Z+]Landroid/media/AudioAttributes;Landroid/media/AudioAttributes;
-HSPLandroid/media/audiopolicy/AudioProductStrategy;->getAudioAttributesForLegacyStreamType(I)Landroid/media/AudioAttributes;+]Landroid/media/audiopolicy/AudioProductStrategy$AudioAttributesGroup;Landroid/media/audiopolicy/AudioProductStrategy$AudioAttributesGroup;
 HSPLandroid/media/audiopolicy/AudioProductStrategy;->getAudioAttributesForStrategyWithLegacyStreamType(I)Landroid/media/AudioAttributes;
 HSPLandroid/media/audiopolicy/AudioProductStrategy;->getAudioProductStrategies()Ljava/util/List;
 HSPLandroid/media/audiopolicy/AudioProductStrategy;->getLegacyStreamTypeForStrategyWithAudioAttributes(Landroid/media/AudioAttributes;)I+]Landroid/media/audiopolicy/AudioProductStrategy;Landroid/media/audiopolicy/AudioProductStrategy;]Ljava/util/List;Ljava/util/ArrayList;]Ljava/util/Iterator;Ljava/util/ArrayList$Itr;
@@ -13125,7 +13115,6 @@
 HSPLandroid/os/ParcelableParcel$1;->createFromParcel(Landroid/os/Parcel;)Landroid/os/ParcelableParcel;
 HSPLandroid/os/ParcelableParcel$1;->createFromParcel(Landroid/os/Parcel;)Ljava/lang/Object;
 HSPLandroid/os/ParcelableParcel;-><init>(Landroid/os/Parcel;Ljava/lang/ClassLoader;)V
-HSPLandroid/os/ParcelableParcel;-><init>(Ljava/lang/ClassLoader;)V
 HSPLandroid/os/ParcelableParcel;->getClassLoader()Ljava/lang/ClassLoader;
 HSPLandroid/os/ParcelableParcel;->getParcel()Landroid/os/Parcel;
 HSPLandroid/os/ParcelableParcel;->writeToParcel(Landroid/os/Parcel;I)V
@@ -13481,7 +13470,6 @@
 HSPLandroid/os/Temperature;-><init>(FILjava/lang/String;I)V
 HSPLandroid/os/Temperature;->getStatus()I
 HSPLandroid/os/Temperature;->isValidStatus(I)Z
-HSPLandroid/os/Temperature;->isValidType(I)Z
 HSPLandroid/os/ThreadLocalWorkSource$$ExternalSyntheticLambda0;->get()Ljava/lang/Object;
 HSPLandroid/os/ThreadLocalWorkSource;->getToken()J+]Ljava/lang/Integer;Ljava/lang/Integer;]Ljava/lang/ThreadLocal;Ljava/lang/ThreadLocal$SuppliedThreadLocal;
 HSPLandroid/os/ThreadLocalWorkSource;->getUid()I+]Ljava/lang/Integer;Ljava/lang/Integer;]Ljava/lang/ThreadLocal;Ljava/lang/ThreadLocal$SuppliedThreadLocal;
@@ -18488,7 +18476,6 @@
 HSPLandroid/view/ViewRootImpl$ImeInputStage;-><init>(Landroid/view/ViewRootImpl;Landroid/view/ViewRootImpl$InputStage;Ljava/lang/String;)V
 HSPLandroid/view/ViewRootImpl$ImeInputStage;->onFinishedInputEvent(Ljava/lang/Object;Z)V
 HSPLandroid/view/ViewRootImpl$ImeInputStage;->onProcess(Landroid/view/ViewRootImpl$QueuedInputEvent;)I
-HSPLandroid/view/ViewRootImpl$InputMetricsListener;-><init>(Landroid/view/ViewRootImpl;)V
 HSPLandroid/view/ViewRootImpl$InputMetricsListener;->onFrameMetricsAvailable(I)V+]Landroid/view/ViewRootImpl$WindowInputEventReceiver;Landroid/view/ViewRootImpl$WindowInputEventReceiver;]Ljava/lang/StringBuilder;Ljava/lang/StringBuilder;]Landroid/view/InputEventReceiver;Landroid/view/ViewRootImpl$WindowInputEventReceiver;
 HSPLandroid/view/ViewRootImpl$InputStage;-><init>(Landroid/view/ViewRootImpl;Landroid/view/ViewRootImpl$InputStage;)V
 HSPLandroid/view/ViewRootImpl$InputStage;->apply(Landroid/view/ViewRootImpl$QueuedInputEvent;I)V+]Landroid/view/ViewRootImpl$InputStage;megamorphic_types
@@ -20395,7 +20382,6 @@
 HSPLandroid/widget/OverScroller$SplineOverScroller;->fling(IIIII)V
 HSPLandroid/widget/OverScroller$SplineOverScroller;->getSplineDeceleration(I)D
 HSPLandroid/widget/OverScroller$SplineOverScroller;->getSplineFlingDistance(I)D
-HSPLandroid/widget/OverScroller$SplineOverScroller;->getSplineFlingDuration(I)I
 HSPLandroid/widget/OverScroller$SplineOverScroller;->onEdgeReached()V
 HSPLandroid/widget/OverScroller$SplineOverScroller;->springback(III)Z
 HSPLandroid/widget/OverScroller$SplineOverScroller;->startScroll(III)V
@@ -22568,10 +22554,7 @@
 HSPLcom/android/internal/widget/LockPatternUtils$StrongAuthTracker$1;->onIsNonStrongBiometricAllowedChanged(ZI)V
 HSPLcom/android/internal/widget/LockPatternUtils$StrongAuthTracker$1;->onStrongAuthRequiredChanged(II)V
 HSPLcom/android/internal/widget/LockPatternUtils$StrongAuthTracker$H;->handleMessage(Landroid/os/Message;)V
-HSPLcom/android/internal/widget/LockPatternUtils$StrongAuthTracker;-><init>(Landroid/content/Context;)V
-HSPLcom/android/internal/widget/LockPatternUtils$StrongAuthTracker;-><init>(Landroid/content/Context;Landroid/os/Looper;)V
 HSPLcom/android/internal/widget/LockPatternUtils$StrongAuthTracker;->getStrongAuthForUser(I)I+]Landroid/util/SparseIntArray;Landroid/util/SparseIntArray;
-HSPLcom/android/internal/widget/LockPatternUtils$StrongAuthTracker;->getStub()Landroid/app/trust/IStrongAuthTracker$Stub;
 HSPLcom/android/internal/widget/LockPatternUtils$StrongAuthTracker;->handleIsNonStrongBiometricAllowedChanged(ZI)V
 HSPLcom/android/internal/widget/LockPatternUtils$StrongAuthTracker;->handleStrongAuthRequiredChanged(II)V
 HSPLcom/android/internal/widget/LockPatternUtils$StrongAuthTracker;->isNonStrongBiometricAllowedAfterIdleTimeout(I)Z
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 59f602c..af4053f 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -1576,7 +1576,7 @@
                     int err;
                     do {
                         err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, nullptr);
-                    } while (err<0 && errno == EINTR);
+                    } while (err == EINTR);
                 }
 
                 checkExit();
diff --git a/config/generate-preloaded-classes.sh b/config/generate-preloaded-classes.sh
deleted file mode 100755
index b17a366..0000000
--- a/config/generate-preloaded-classes.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/bash
-#
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-if [ "$#" -lt 2 ]; then
-  echo "Usage $0 <input classes file> <denylist file> [extra classes files]"
-  exit 1
-fi
-
-# Write file headers first
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-cat "$DIR/copyright-header"
-echo "# Preloaded-classes filter file for phones.
-#
-# Classes in this file will be allocated into the boot image, and forcibly initialized in
-# the zygote during initialization. This is a trade-off, using virtual address space to share
-# common heap between apps.
-#
-# This file has been derived for mainline phone (and tablet) usage.
-#"
-
-input=$1
-denylist=$2
-shift 2
-extra_classes_files=("$@")
-
-# Disable locale to enable lexicographical sorting
-LC_ALL=C sort "$input" "${extra_classes_files[@]}" | uniq | grep -f "$denylist" -v -F -x | grep -v "\$NoPreloadHolder"
diff --git a/config/preloaded-classes-extra b/config/preloaded-classes-extra
deleted file mode 100644
index 09f393a..0000000
--- a/config/preloaded-classes-extra
+++ /dev/null
@@ -1,14 +0,0 @@
-android.icu.impl.coll.CollationRoot
-android.icu.impl.IDNA2003
-android.icu.impl.number.Parse
-android.icu.util.TimeZone
-android.media.ImageReader
-android.media.MediaCodecList
-android.media.MediaPlayer
-android.media.SoundPool
-android.text.format.Formatter
-android.text.Html$HtmlParser
-android.util.Log$PreloadHolder
-com.android.org.conscrypt.TrustedCertificateStore
-org.ccil.cowan.tagsoup.HTMLScanner
-sun.security.jca.Providers
diff --git a/core/api/Android.bp b/core/api/Android.bp
index 170febb..114a957 100644
--- a/core/api/Android.bp
+++ b/core/api/Android.bp
@@ -51,11 +51,17 @@
 filegroup {
     name: "non-updatable-module-lib-current.txt",
     srcs: ["module-lib-current.txt"],
-    visibility: ["//frameworks/base/api"],
+    visibility: [
+        "//frameworks/base/api",
+        "//cts/tests/signature/api",
+    ],
 }
 
 filegroup {
     name: "non-updatable-module-lib-removed.txt",
     srcs: ["module-lib-removed.txt"],
-    visibility: ["//frameworks/base/api"],
+    visibility: [
+        "//frameworks/base/api",
+        "//cts/tests/signature/api",
+    ],
 }
diff --git a/core/api/current.txt b/core/api/current.txt
index 5656c31..b40a3e5 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1204,6 +1204,7 @@
     field public static final int requiredSplitTypes;
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
+    field public static final int resetEnabledSettingsOnAppDataCleared;
     field public static final int resizeClip = 16843983; // 0x10104cf
     field public static final int resizeMode = 16843619; // 0x1010363
     field public static final int resizeable = 16843405; // 0x101028d
@@ -1409,6 +1410,7 @@
     field public static final int summaryColumn = 16843426; // 0x10102a2
     field public static final int summaryOff = 16843248; // 0x10101f0
     field public static final int summaryOn = 16843247; // 0x10101ef
+    field public static final int supportedTypes;
     field public static final int supportsAssist = 16844016; // 0x10104f0
     field public static final int supportsInlineSuggestions = 16844301; // 0x101060d
     field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
@@ -3253,19 +3255,41 @@
     method public boolean willContinue();
   }
 
+  public final class MagnificationConfig implements android.os.Parcelable {
+    method public int describeContents();
+    method public float getCenterX();
+    method public float getCenterY();
+    method public int getMode();
+    method public float getScale();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.accessibilityservice.MagnificationConfig> CREATOR;
+    field public static final int DEFAULT_MODE = 0; // 0x0
+    field public static final int FULLSCREEN_MODE = 1; // 0x1
+    field public static final int WINDOW_MODE = 2; // 0x2
+  }
+
+  public static final class MagnificationConfig.Builder {
+    ctor public MagnificationConfig.Builder();
+    method @NonNull public android.accessibilityservice.MagnificationConfig build();
+    method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setCenterX(float);
+    method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setCenterY(float);
+    method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setMode(int);
+    method @NonNull public android.accessibilityservice.MagnificationConfig.Builder setScale(float);
+  }
+
   public final class TouchInteractionController {
-    method public void addListener(@Nullable java.util.concurrent.Executor, @NonNull android.accessibilityservice.TouchInteractionController.Listener);
     method public int getDisplayId();
     method public int getMaxPointerCount();
     method public int getState();
     method public void performClick();
     method public void performLongClickAndStartDrag();
-    method public void removeAllListeners();
-    method public boolean removeListener(@NonNull android.accessibilityservice.TouchInteractionController.Listener);
+    method public void registerCallback(@Nullable java.util.concurrent.Executor, @NonNull android.accessibilityservice.TouchInteractionController.Callback);
     method public void requestDelegating();
     method public void requestDragging(int);
     method public void requestTouchExploration();
     method @NonNull public static String stateToString(int);
+    method public void unregisterAllCallbacks();
+    method public boolean unregisterCallback(@NonNull android.accessibilityservice.TouchInteractionController.Callback);
     field public static final int STATE_CLEAR = 0; // 0x0
     field public static final int STATE_DELEGATING = 4; // 0x4
     field public static final int STATE_DRAGGING = 3; // 0x3
@@ -3273,7 +3297,7 @@
     field public static final int STATE_TOUCH_INTERACTING = 1; // 0x1
   }
 
-  public static interface TouchInteractionController.Listener {
+  public static interface TouchInteractionController.Callback {
     method public void onMotionEvent(@NonNull android.view.MotionEvent);
     method public void onStateChanged(int);
   }
@@ -8718,6 +8742,7 @@
     method public android.bluetooth.le.BluetoothLeScanner getBluetoothLeScanner();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public java.util.Set<android.bluetooth.BluetoothDevice> getBondedDevices();
     method @Deprecated public static android.bluetooth.BluetoothAdapter getDefaultAdapter();
+    method @Nullable @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) public java.time.Duration getDiscoverableTimeout();
     method public int getLeMaximumAdvertisingDataLength();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public String getName();
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int getProfileConnectionState(int);
@@ -9012,11 +9037,15 @@
 
   public final class BluetoothClass implements android.os.Parcelable {
     method public int describeContents();
+    method public boolean doesClassMatch(int);
     method public int getDeviceClass();
     method public int getMajorDeviceClass();
     method public boolean hasService(int);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothClass> CREATOR;
+    field public static final int PROFILE_A2DP = 1; // 0x1
+    field public static final int PROFILE_HEADSET = 0; // 0x0
+    field public static final int PROFILE_HID = 3; // 0x3
   }
 
   public static class BluetoothClass.Device {
@@ -9330,7 +9359,8 @@
     method public java.util.List<android.bluetooth.BluetoothDevice> getDevicesMatchingConnectionStates(int[]);
     method public android.bluetooth.BluetoothGattService getService(java.util.UUID);
     method public java.util.List<android.bluetooth.BluetoothGattService> getServices();
-    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean notifyCharacteristicChanged(android.bluetooth.BluetoothDevice, android.bluetooth.BluetoothGattCharacteristic, boolean);
+    method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public int notifyCharacteristicChanged(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothGattCharacteristic, boolean, @NonNull byte[]);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void readPhy(android.bluetooth.BluetoothDevice);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean removeService(android.bluetooth.BluetoothGattService);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean sendResponse(android.bluetooth.BluetoothDevice, int, int, int, byte[]);
@@ -9624,6 +9654,7 @@
     method public java.util.Map<android.os.ParcelUuid,byte[]> getServiceData();
     method @NonNull public java.util.List<android.os.ParcelUuid> getServiceSolicitationUuids();
     method public java.util.List<android.os.ParcelUuid> getServiceUuids();
+    method @NonNull public java.util.List<android.bluetooth.le.TransportDiscoveryData> getTransportDiscoveryData();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.AdvertiseData> CREATOR;
   }
@@ -9634,6 +9665,7 @@
     method public android.bluetooth.le.AdvertiseData.Builder addServiceData(android.os.ParcelUuid, byte[]);
     method @NonNull public android.bluetooth.le.AdvertiseData.Builder addServiceSolicitationUuid(@NonNull android.os.ParcelUuid);
     method public android.bluetooth.le.AdvertiseData.Builder addServiceUuid(android.os.ParcelUuid);
+    method @NonNull public android.bluetooth.le.AdvertiseData.Builder addTransportDiscoveryData(@NonNull android.bluetooth.le.TransportDiscoveryData);
     method public android.bluetooth.le.AdvertiseData build();
     method public android.bluetooth.le.AdvertiseData.Builder setIncludeDeviceName(boolean);
     method public android.bluetooth.le.AdvertiseData.Builder setIncludeTxPowerLevel(boolean);
@@ -9893,10 +9925,45 @@
     method public android.bluetooth.le.ScanSettings.Builder setScanMode(int);
   }
 
+  public final class TransportBlock implements android.os.Parcelable {
+    ctor public TransportBlock(int, int, int, @Nullable byte[]);
+    method public int describeContents();
+    method public int getOrgId();
+    method public int getTdsFlags();
+    method @Nullable public byte[] getTransportData();
+    method public int getTransportDataLength();
+    method @Nullable public byte[] toByteArray();
+    method public int totalBytes();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportBlock> CREATOR;
+  }
+
+  public final class TransportDiscoveryData implements android.os.Parcelable {
+    ctor public TransportDiscoveryData(int, @NonNull java.util.List<android.bluetooth.le.TransportBlock>);
+    ctor public TransportDiscoveryData(@NonNull byte[]);
+    method public int describeContents();
+    method @NonNull public java.util.List<android.bluetooth.le.TransportBlock> getTransportBlocks();
+    method public int getTransportDataType();
+    method @Nullable public byte[] toByteArray();
+    method public int totalBytes();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.bluetooth.le.TransportDiscoveryData> CREATOR;
+  }
+
 }
 
 package android.companion {
 
+  public final class AssociationInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public android.net.MacAddress getDeviceMacAddress();
+    method @Nullable public String getDeviceProfile();
+    method @Nullable public CharSequence getDisplayName();
+    method public int getId();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.companion.AssociationInfo> CREATOR;
+  }
+
   public final class AssociationRequest implements android.os.Parcelable {
     method public int describeContents();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -9909,6 +9976,7 @@
     method @NonNull public android.companion.AssociationRequest.Builder addDeviceFilter(@Nullable android.companion.DeviceFilter<?>);
     method @NonNull public android.companion.AssociationRequest build();
     method @NonNull public android.companion.AssociationRequest.Builder setDeviceProfile(@NonNull String);
+    method @NonNull public android.companion.AssociationRequest.Builder setDisplayName(@NonNull CharSequence);
     method @NonNull public android.companion.AssociationRequest.Builder setSingleDevice(boolean);
   }
 
@@ -9944,20 +10012,26 @@
   }
 
   public final class CompanionDeviceManager {
-    method @RequiresPermission(value=android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH, conditional=true) public void associate(@NonNull android.companion.AssociationRequest, @NonNull android.companion.CompanionDeviceManager.Callback, @Nullable android.os.Handler);
-    method public void disassociate(@NonNull String);
-    method @NonNull public java.util.List<java.lang.String> getAssociations();
+    method @RequiresPermission(anyOf={android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH, "android.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING", "android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION"}, conditional=true) public void associate(@NonNull android.companion.AssociationRequest, @NonNull android.companion.CompanionDeviceManager.Callback, @Nullable android.os.Handler);
+    method @RequiresPermission(anyOf={android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH, "android.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING", "android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION"}, conditional=true) public void associate(@NonNull android.companion.AssociationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.Callback);
+    method @Deprecated public void disassociate(@NonNull String);
+    method public void disassociate(int);
+    method @Deprecated @NonNull public java.util.List<java.lang.String> getAssociations();
+    method @NonNull public java.util.List<android.companion.AssociationInfo> getMyAssociations();
     method @Deprecated public boolean hasNotificationAccess(android.content.ComponentName);
     method public void requestNotificationAccess(android.content.ComponentName);
     method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void startObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException;
     method @RequiresPermission(android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE) public void stopObservingDevicePresence(@NonNull String) throws android.companion.DeviceNotAssociatedException;
-    field public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE";
+    field public static final String EXTRA_ASSOCIATION = "android.companion.extra.ASSOCIATION";
+    field @Deprecated public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE";
   }
 
   public abstract static class CompanionDeviceManager.Callback {
     ctor public CompanionDeviceManager.Callback();
-    method public abstract void onDeviceFound(android.content.IntentSender);
-    method public abstract void onFailure(CharSequence);
+    method public void onAssociationCreated(@NonNull android.companion.AssociationInfo);
+    method public void onAssociationPending(@NonNull android.content.IntentSender);
+    method @Deprecated public void onDeviceFound(@NonNull android.content.IntentSender);
+    method public abstract void onFailure(@Nullable CharSequence);
   }
 
   public abstract class CompanionDeviceService extends android.app.Service {
@@ -10793,6 +10867,7 @@
     field public static final String STATUS_BAR_SERVICE = "statusbar";
     field public static final String STORAGE_SERVICE = "storage";
     field public static final String STORAGE_STATS_SERVICE = "storagestats";
+    field public static final String SUPPLEMENTAL_PROCESS_SERVICE = "supplemental_process";
     field public static final String SYSTEM_HEALTH_SERVICE = "systemhealth";
     field public static final String TELECOM_SERVICE = "telecom";
     field public static final String TELEPHONY_IMS_SERVICE = "telephony_ims";
@@ -11249,6 +11324,7 @@
     field public static final String ACTION_QUICK_VIEW = "android.intent.action.QUICK_VIEW";
     field public static final String ACTION_REBOOT = "android.intent.action.REBOOT";
     field public static final String ACTION_RUN = "android.intent.action.RUN";
+    field public static final String ACTION_SAFETY_CENTER = "android.intent.action.SAFETY_CENTER";
     field public static final String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
     field public static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
     field public static final String ACTION_SEARCH = "android.intent.action.SEARCH";
@@ -12502,6 +12578,7 @@
     method @NonNull public java.io.OutputStream openWrite(@NonNull String, long, long) throws java.io.IOException;
     method public void removeChildSessionId(int);
     method public void removeSplit(@NonNull String) throws java.io.IOException;
+    method public void requestChecksums(@NonNull String, int, @NonNull java.util.List<java.security.cert.Certificate>, @NonNull android.content.pm.PackageManager.OnChecksumsReadyListener) throws java.security.cert.CertificateEncodingException, java.io.FileNotFoundException;
     method @Deprecated public void setChecksums(@NonNull String, @NonNull java.util.List<android.content.pm.Checksum>, @Nullable byte[]) throws java.io.IOException;
     method public void setStagingProgress(float);
     method public void transfer(@NonNull String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -16457,11 +16534,13 @@
 
   public class AdaptiveIconDrawable extends android.graphics.drawable.Drawable implements android.graphics.drawable.Drawable.Callback {
     ctor public AdaptiveIconDrawable(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
+    ctor public AdaptiveIconDrawable(@Nullable android.graphics.drawable.Drawable, @Nullable android.graphics.drawable.Drawable, @Nullable android.graphics.drawable.Drawable);
     method public void draw(android.graphics.Canvas);
     method public android.graphics.drawable.Drawable getBackground();
     method public static float getExtraInsetFraction();
     method public android.graphics.drawable.Drawable getForeground();
     method public android.graphics.Path getIconMask();
+    method @Nullable public android.graphics.drawable.Drawable getMonochrome();
     method public int getOpacity();
     method public void invalidateDrawable(@NonNull android.graphics.drawable.Drawable);
     method public void scheduleDrawable(@NonNull android.graphics.drawable.Drawable, @NonNull Runnable, long);
@@ -17271,8 +17350,12 @@
     method @NonNull public android.graphics.text.MeasuredText.Builder appendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @FloatRange(from=0) @Px float);
     method @NonNull public android.graphics.text.MeasuredText.Builder appendStyleRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, boolean);
     method @NonNull public android.graphics.text.MeasuredText build();
-    method @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean);
+    method @Deprecated @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean);
+    method @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(int);
     method @NonNull public android.graphics.text.MeasuredText.Builder setComputeLayout(boolean);
+    field public static final int HYPHENATION_MODE_FAST = 2; // 0x2
+    field public static final int HYPHENATION_MODE_NONE = 0; // 0x0
+    field public static final int HYPHENATION_MODE_NORMAL = 1; // 0x1
   }
 
   public final class PositionedGlyphs {
@@ -20626,6 +20709,7 @@
     method public boolean isMicrophoneMute();
     method public boolean isMusicActive();
     method public static boolean isOffloadedPlaybackSupported(@NonNull android.media.AudioFormat, @NonNull android.media.AudioAttributes);
+    method public boolean isRampingRingerEnabled();
     method public boolean isSpeakerphoneOn();
     method public boolean isStreamMute(int);
     method public boolean isSurroundFormatEnabled(int);
@@ -20732,7 +20816,9 @@
     field public static final int GET_DEVICES_ALL = 3; // 0x3
     field public static final int GET_DEVICES_INPUTS = 1; // 0x1
     field public static final int GET_DEVICES_OUTPUTS = 2; // 0x2
+    field public static final int MODE_CALL_REDIRECT = 5; // 0x5
     field public static final int MODE_CALL_SCREENING = 4; // 0x4
+    field public static final int MODE_COMMUNICATION_REDIRECT = 6; // 0x6
     field public static final int MODE_CURRENT = -1; // 0xffffffff
     field public static final int MODE_INVALID = -2; // 0xfffffffe
     field public static final int MODE_IN_CALL = 2; // 0x2
@@ -26304,6 +26390,13 @@
   public final class TvIAppManager {
   }
 
+  public abstract class TvIAppService extends android.app.Service {
+    ctor public TvIAppService();
+    method public final android.os.IBinder onBind(android.content.Intent);
+    field public static final String SERVICE_INTERFACE = "android.media.tv.interactive.TvIAppService";
+    field public static final String SERVICE_META_DATA = "android.media.tv.interactive.app";
+  }
+
 }
 
 package android.mtp {
@@ -27595,6 +27688,7 @@
     field public static final String CATEGORY_PAYMENT = "payment";
     field public static final String EXTRA_CATEGORY = "category";
     field public static final String EXTRA_SERVICE_COMPONENT = "component";
+    field public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID";
     field public static final int SELECTION_MODE_ALWAYS_ASK = 1; // 0x1
     field public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2; // 0x2
     field public static final int SELECTION_MODE_PREFER_DEFAULT = 0; // 0x0
@@ -31656,9 +31750,9 @@
     method public byte[] marshall();
     method @NonNull public static android.os.Parcel obtain();
     method @NonNull public static android.os.Parcel obtain(@NonNull android.os.IBinder);
-    method @Nullable public Object[] readArray(@Nullable ClassLoader);
+    method @Deprecated @Nullable public Object[] readArray(@Nullable ClassLoader);
     method @Nullable public <T> T[] readArray(@Nullable ClassLoader, @NonNull Class<T>);
-    method @Nullable public java.util.ArrayList readArrayList(@Nullable ClassLoader);
+    method @Deprecated @Nullable public java.util.ArrayList readArrayList(@Nullable ClassLoader);
     method @Nullable public <T> java.util.ArrayList<T> readArrayList(@Nullable ClassLoader, @NonNull Class<? extends T>);
     method public void readBinderArray(@NonNull android.os.IBinder[]);
     method public void readBinderList(@NonNull java.util.List<android.os.IBinder>);
@@ -31676,32 +31770,32 @@
     method public android.os.ParcelFileDescriptor readFileDescriptor();
     method public float readFloat();
     method public void readFloatArray(@NonNull float[]);
-    method @Nullable public java.util.HashMap readHashMap(@Nullable ClassLoader);
+    method @Deprecated @Nullable public java.util.HashMap readHashMap(@Nullable ClassLoader);
     method @Nullable public <K, V> java.util.HashMap<K,V> readHashMap(@Nullable ClassLoader, @NonNull Class<? extends K>, @NonNull Class<? extends V>);
     method public int readInt();
     method public void readIntArray(@NonNull int[]);
     method public <T extends android.os.IInterface> void readInterfaceArray(@NonNull T[], @NonNull java.util.function.Function<android.os.IBinder,T>);
     method public <T extends android.os.IInterface> void readInterfaceList(@NonNull java.util.List<T>, @NonNull java.util.function.Function<android.os.IBinder,T>);
-    method public void readList(@NonNull java.util.List, @Nullable ClassLoader);
+    method @Deprecated public void readList(@NonNull java.util.List, @Nullable ClassLoader);
     method public <T> void readList(@NonNull java.util.List<? super T>, @Nullable ClassLoader, @NonNull Class<T>);
     method public long readLong();
     method public void readLongArray(@NonNull long[]);
-    method public void readMap(@NonNull java.util.Map, @Nullable ClassLoader);
+    method @Deprecated public void readMap(@NonNull java.util.Map, @Nullable ClassLoader);
     method public <K, V> void readMap(@NonNull java.util.Map<? super K,? super V>, @Nullable ClassLoader, @NonNull Class<K>, @NonNull Class<V>);
-    method @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader);
+    method @Deprecated @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader);
     method @Nullable public <T extends android.os.Parcelable> T readParcelable(@Nullable ClassLoader, @NonNull Class<T>);
     method @Nullable public android.os.Parcelable[] readParcelableArray(@Nullable ClassLoader);
     method @Nullable public <T> T[] readParcelableArray(@Nullable ClassLoader, @NonNull Class<T>);
-    method @Nullable public android.os.Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader);
+    method @Deprecated @Nullable public android.os.Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader);
     method @Nullable public <T> android.os.Parcelable.Creator<T> readParcelableCreator(@Nullable ClassLoader, @NonNull Class<T>);
     method @NonNull public <T extends android.os.Parcelable> java.util.List<T> readParcelableList(@NonNull java.util.List<T>, @Nullable ClassLoader);
     method @Nullable public android.os.PersistableBundle readPersistableBundle();
     method @Nullable public android.os.PersistableBundle readPersistableBundle(@Nullable ClassLoader);
-    method @Nullable public java.io.Serializable readSerializable();
+    method @Deprecated @Nullable public java.io.Serializable readSerializable();
     method @Nullable public <T extends java.io.Serializable> T readSerializable(@Nullable ClassLoader, @NonNull Class<T>);
     method @NonNull public android.util.Size readSize();
     method @NonNull public android.util.SizeF readSizeF();
-    method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader);
+    method @Deprecated @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader);
     method @Nullable public <T> android.util.SparseArray<T> readSparseArray(@Nullable ClassLoader, @NonNull Class<? extends T>);
     method @Nullable public android.util.SparseBooleanArray readSparseBooleanArray();
     method @Nullable public String readString();
@@ -31957,8 +32051,10 @@
     method public static final long getElapsedCpuTime();
     method public static final int[] getExclusiveCores();
     method public static final int getGidForName(String);
-    method public static final long getStartElapsedRealtime();
-    method public static final long getStartUptimeMillis();
+    method public static long getStartElapsedRealtime();
+    method public static long getStartRequestedElapsedRealtime();
+    method public static long getStartRequestedUptimeMillis();
+    method public static long getStartUptimeMillis();
     method public static final int getThreadPriority(int) throws java.lang.IllegalArgumentException;
     method public static final int getUidForName(String);
     method public static final boolean is64Bit();
@@ -31966,6 +32062,7 @@
     method public static final boolean isIsolated();
     method public static final void killProcess(int);
     method public static final int myPid();
+    method @NonNull public static String myProcessName();
     method public static final int myTid();
     method public static final int myUid();
     method public static android.os.UserHandle myUserHandle();
@@ -32301,6 +32398,7 @@
     field public static final String DISALLOW_SET_WALLPAPER = "no_set_wallpaper";
     field public static final String DISALLOW_SHARE_INTO_MANAGED_PROFILE = "no_sharing_into_profile";
     field public static final String DISALLOW_SHARE_LOCATION = "no_share_location";
+    field public static final String DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI = "no_sharing_admin_configured_wifi";
     field public static final String DISALLOW_SMS = "no_sms";
     field public static final String DISALLOW_SYSTEM_ERROR_DIALOGS = "no_system_error_dialogs";
     field public static final String DISALLOW_UNIFIED_PASSWORD = "no_unified_password";
@@ -32328,6 +32426,7 @@
   }
 
   public final class VibrationAttributes implements android.os.Parcelable {
+    method @NonNull public static android.os.VibrationAttributes createForUsage(int);
     method public int describeContents();
     method public int getFlags();
     method public int getUsage();
@@ -32336,13 +32435,16 @@
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationAttributes> CREATOR;
     field public static final int FLAG_BYPASS_INTERRUPTION_POLICY = 1; // 0x1
+    field public static final int USAGE_ACCESSIBILITY = 66; // 0x42
     field public static final int USAGE_ALARM = 17; // 0x11
     field public static final int USAGE_CLASS_ALARM = 1; // 0x1
     field public static final int USAGE_CLASS_FEEDBACK = 2; // 0x2
     field public static final int USAGE_CLASS_MASK = 15; // 0xf
+    field public static final int USAGE_CLASS_MEDIA = 3; // 0x3
     field public static final int USAGE_CLASS_UNKNOWN = 0; // 0x0
     field public static final int USAGE_COMMUNICATION_REQUEST = 65; // 0x41
     field public static final int USAGE_HARDWARE_FEEDBACK = 50; // 0x32
+    field public static final int USAGE_MEDIA = 19; // 0x13
     field public static final int USAGE_NOTIFICATION = 49; // 0x31
     field public static final int USAGE_PHYSICAL_EMULATION = 34; // 0x22
     field public static final int USAGE_RINGTONE = 33; // 0x21
@@ -32353,6 +32455,7 @@
   public static final class VibrationAttributes.Builder {
     ctor public VibrationAttributes.Builder();
     ctor public VibrationAttributes.Builder(@Nullable android.os.VibrationAttributes);
+    ctor public VibrationAttributes.Builder(@NonNull android.media.AudioAttributes);
     method @NonNull public android.os.VibrationAttributes build();
     method @NonNull public android.os.VibrationAttributes.Builder setFlags(int, int);
     method @NonNull public android.os.VibrationAttributes.Builder setUsage(int);
@@ -32403,7 +32506,8 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(long[], int);
     method @Deprecated @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(long[], int, android.media.AudioAttributes);
     method @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(android.os.VibrationEffect);
-    method @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(android.os.VibrationEffect, android.media.AudioAttributes);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(android.os.VibrationEffect, android.media.AudioAttributes);
+    method @RequiresPermission(android.Manifest.permission.VIBRATE) public void vibrate(@NonNull android.os.VibrationEffect, @NonNull android.os.VibrationAttributes);
     field public static final int VIBRATION_EFFECT_SUPPORT_NO = 2; // 0x2
     field public static final int VIBRATION_EFFECT_SUPPORT_UNKNOWN = 0; // 0x0
     field public static final int VIBRATION_EFFECT_SUPPORT_YES = 1; // 0x1
@@ -35522,7 +35626,7 @@
     field public static final String AIRPLANE_MODE_RADIOS = "airplane_mode_radios";
     field public static final String ALWAYS_FINISH_ACTIVITIES = "always_finish_activities";
     field public static final String ANIMATOR_DURATION_SCALE = "animator_duration_scale";
-    field public static final String APPLY_RAMPING_RINGER = "apply_ramping_ringer";
+    field @Deprecated public static final String APPLY_RAMPING_RINGER = "apply_ramping_ringer";
     field public static final String AUTO_TIME = "auto_time";
     field public static final String AUTO_TIME_ZONE = "auto_time_zone";
     field public static final String BLUETOOTH_ON = "bluetooth_on";
@@ -40628,7 +40732,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getCallCapablePhoneAccounts();
     method public String getDefaultDialerPackage();
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telecom.PhoneAccountHandle getDefaultOutgoingPhoneAccount(String);
-    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_SMS, android.Manifest.permission.READ_PHONE_NUMBERS}, conditional=true) public String getLine1Number(android.telecom.PhoneAccountHandle);
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_SMS, android.Manifest.permission.READ_PHONE_NUMBERS}, conditional=true) public String getLine1Number(android.telecom.PhoneAccountHandle);
     method public android.telecom.PhoneAccount getPhoneAccount(android.telecom.PhoneAccountHandle);
     method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telecom.PhoneAccountHandle> getSelfManagedPhoneAccounts();
     method public android.telecom.PhoneAccountHandle getSimCallManager();
@@ -42696,7 +42800,8 @@
     method @Nullable public String getMccString();
     method @Deprecated public int getMnc();
     method @Nullable public String getMncString();
-    method public String getNumber();
+    method @Deprecated public String getNumber();
+    method public int getPortIndex();
     method public int getSimSlotIndex();
     method public int getSubscriptionId();
     method public int getSubscriptionType();
@@ -42729,6 +42834,8 @@
     method @NonNull public java.util.List<android.net.Uri> getDeviceToDeviceStatusSharingContacts(int);
     method public int getDeviceToDeviceStatusSharingPreference(int);
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List<android.telephony.SubscriptionInfo> getOpportunisticSubscriptions();
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_NUMBERS, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public String getPhoneNumber(int, int);
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_NUMBERS, "android.permission.READ_PRIVILEGED_PHONE_STATE"}) public String getPhoneNumber(int);
     method public static int getSlotIndex(int);
     method @Nullable public int[] getSubscriptionIds(int);
     method @NonNull public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
@@ -42740,6 +42847,7 @@
     method public void removeOnOpportunisticSubscriptionsChangedListener(@NonNull android.telephony.SubscriptionManager.OnOpportunisticSubscriptionsChangedListener);
     method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void removeSubscriptionsFromGroup(@NonNull java.util.List<java.lang.Integer>, @NonNull android.os.ParcelUuid);
+    method public void setCarrierPhoneNumber(int, @NonNull String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDeviceToDeviceStatusSharingContacts(int, @NonNull java.util.List<android.net.Uri>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDeviceToDeviceStatusSharingPreference(int, int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setOpportunistic(boolean, int);
@@ -42766,6 +42874,9 @@
     field public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
     field public static final int INVALID_SIM_SLOT_INDEX = -1; // 0xffffffff
     field public static final int INVALID_SUBSCRIPTION_ID = -1; // 0xffffffff
+    field public static final int PHONE_NUMBER_SOURCE_CARRIER = 2; // 0x2
+    field public static final int PHONE_NUMBER_SOURCE_IMS = 3; // 0x3
+    field public static final int PHONE_NUMBER_SOURCE_UICC = 1; // 0x1
     field public static final int SUBSCRIPTION_TYPE_LOCAL_SIM = 0; // 0x0
     field public static final int SUBSCRIPTION_TYPE_REMOTE_SIM = 1; // 0x1
   }
@@ -42944,7 +43055,7 @@
     method public String getIccAuthentication(int, int, String);
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getImei();
     method @RequiresPermission("android.permission.READ_PRIVILEGED_PHONE_STATE") public String getImei(int);
-    method @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_SMS, android.Manifest.permission.READ_PHONE_NUMBERS}) public String getLine1Number();
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.READ_SMS, android.Manifest.permission.READ_PHONE_NUMBERS}) public String getLine1Number();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public String getManualNetworkSelectionPlmn();
     method @Nullable public String getManufacturerCode();
     method @Nullable public String getManufacturerCode(int);
@@ -43029,7 +43140,7 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataEnabledForReason(int, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setForbiddenPlmns(@NonNull java.util.List<java.lang.String>);
-    method public boolean setLine1NumberForDisplay(String, String);
+    method @Deprecated public boolean setLine1NumberForDisplay(String, String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setNetworkSelectionModeAutomatic();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(String, boolean);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setNetworkSelectionModeManual(@NonNull String, boolean, int);
@@ -43240,14 +43351,28 @@
     method public int describeContents();
     method public int getCardId();
     method @Nullable public String getEid();
-    method @Nullable public String getIccId();
-    method public int getSlotIndex();
+    method @Deprecated @Nullable public String getIccId();
+    method public int getPhysicalSlotIndex();
+    method @NonNull public java.util.Collection<android.telephony.UiccPortInfo> getPorts();
+    method @Deprecated public int getSlotIndex();
     method public boolean isEuicc();
+    method public boolean isMultipleEnabledProfilesSupported();
     method public boolean isRemovable();
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccCardInfo> CREATOR;
   }
 
+  public final class UiccPortInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public String getIccId();
+    method @IntRange(from=0) public int getLogicalSlotIndex();
+    method @IntRange(from=0) public int getPortIndex();
+    method public boolean isActive();
+    method public void writeToParcel(@Nullable android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccPortInfo> CREATOR;
+    field public static final String ICCID_REDACTED = "FFFFFFFFFFFFFFFFFFFF";
+  }
+
   public abstract class VisualVoicemailService extends android.app.Service {
     ctor public VisualVoicemailService();
     method public android.os.IBinder onBind(android.content.Intent);
@@ -43548,8 +43673,10 @@
     method @Nullable public String getEid();
     method @Nullable public android.telephony.euicc.EuiccInfo getEuiccInfo();
     method public boolean isEnabled();
+    method public boolean isSimPortAvailable(int);
     method public void startResolutionActivity(android.app.Activity, int, android.content.Intent, android.app.PendingIntent) throws android.content.IntentSender.SendIntentException;
-    method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
+    method @Deprecated @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, android.app.PendingIntent);
+    method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void switchToSubscription(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.euicc.EuiccManager.ResultListener);
     method @RequiresPermission("android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS") public void updateSubscriptionNickname(int, @Nullable String, @NonNull android.app.PendingIntent);
     field public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
     field public static final String ACTION_NOTIFY_CARRIER_SETUP_INCOMPLETE = "android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE";
@@ -43595,6 +43722,10 @@
     field public static final int OPERATION_SYSTEM = 1; // 0x1
   }
 
+  public static interface EuiccManager.ResultListener {
+    method public void onComplete(int, @Nullable android.content.Intent);
+  }
+
 }
 
 package android.telephony.gsm {
@@ -44479,8 +44610,10 @@
     field public static final int DIR_LEFT_TO_RIGHT = 1; // 0x1
     field public static final int DIR_RIGHT_TO_LEFT = -1; // 0xffffffff
     field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
+    field public static final int HYPHENATION_FREQUENCY_FULL_FAST = 4; // 0x4
     field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
     field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
+    field public static final int HYPHENATION_FREQUENCY_NORMAL_FAST = 3; // 0x3
     field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
     field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
   }
@@ -51051,6 +51184,7 @@
     method public int getRecommendedTimeoutMillis(int, int);
     method public void interrupt();
     method public static boolean isAccessibilityButtonSupported();
+    method public boolean isAudioDescriptionRequested();
     method public boolean isEnabled();
     method public boolean isTouchExplorationEnabled();
     method public void removeAccessibilityRequestPreparer(android.view.accessibility.AccessibilityRequestPreparer);
@@ -51344,14 +51478,18 @@
   public static final class AccessibilityNodeInfo.CollectionItemInfo {
     ctor public AccessibilityNodeInfo.CollectionItemInfo(int, int, int, int, boolean);
     ctor public AccessibilityNodeInfo.CollectionItemInfo(int, int, int, int, boolean, boolean);
+    ctor public AccessibilityNodeInfo.CollectionItemInfo(@Nullable String, int, int, @Nullable String, int, int, boolean, boolean);
     method public int getColumnIndex();
     method public int getColumnSpan();
+    method @Nullable public String getColumnTitle();
     method public int getRowIndex();
     method public int getRowSpan();
+    method @Nullable public String getRowTitle();
     method @Deprecated public boolean isHeading();
     method public boolean isSelected();
     method public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean);
     method public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean, boolean);
+    method @NonNull public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(@Nullable String, int, int, @Nullable String, int, int, boolean, boolean);
   }
 
   public static final class AccessibilityNodeInfo.ExtraRenderingInfo {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
old mode 100755
new mode 100644
index a255ce3..dd1760c
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -32,6 +32,7 @@
     field public static final String AMBIENT_WALLPAPER = "android.permission.AMBIENT_WALLPAPER";
     field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
     field public static final String ASSOCIATE_COMPANION_DEVICES = "android.permission.ASSOCIATE_COMPANION_DEVICES";
+    field public static final String AUTOMOTIVE_GNSS_CONTROLS = "android.permission.AUTOMOTIVE_GNSS_CONTROLS";
     field public static final String BACKGROUND_CAMERA = "android.permission.BACKGROUND_CAMERA";
     field public static final String BACKUP = "android.permission.BACKUP";
     field public static final String BATTERY_PREDICTION = "android.permission.BATTERY_PREDICTION";
@@ -255,7 +256,8 @@
     field public static final String RENOUNCE_PERMISSIONS = "android.permission.RENOUNCE_PERMISSIONS";
     field public static final String REQUEST_COMPANION_PROFILE_APP_STREAMING = "android.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING";
     field public static final String REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION = "android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION";
-    field public static final String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
+    field public static final String REQUEST_COMPANION_SELF_MANAGED = "android.permission.REQUEST_COMPANION_SELF_MANAGED";
+    field @Deprecated public static final String REQUEST_NETWORK_SCORES = "android.permission.REQUEST_NETWORK_SCORES";
     field public static final String REQUEST_NOTIFICATION_ASSISTANT_SERVICE = "android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE";
     field public static final String RESET_PASSWORD = "android.permission.RESET_PASSWORD";
     field public static final String RESTART_WIFI_SUBSYSTEM = "android.permission.RESTART_WIFI_SUBSYSTEM";
@@ -266,10 +268,11 @@
     field public static final String REVOKE_RUNTIME_PERMISSIONS = "android.permission.REVOKE_RUNTIME_PERMISSIONS";
     field public static final String ROTATE_SURFACE_FLINGER = "android.permission.ROTATE_SURFACE_FLINGER";
     field public static final String SCHEDULE_PRIORITIZED_ALARM = "android.permission.SCHEDULE_PRIORITIZED_ALARM";
-    field public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
+    field @Deprecated public static final String SCORE_NETWORKS = "android.permission.SCORE_NETWORKS";
     field public static final String SECURE_ELEMENT_PRIVILEGED_OPERATION = "android.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION";
     field public static final String SEND_CATEGORY_CAR_NOTIFICATIONS = "android.permission.SEND_CATEGORY_CAR_NOTIFICATIONS";
     field public static final String SEND_DEVICE_CUSTOMIZATION_READY = "android.permission.SEND_DEVICE_CUSTOMIZATION_READY";
+    field public static final String SEND_SAFETY_CENTER_UPDATE = "android.permission.SEND_SAFETY_CENTER_UPDATE";
     field public static final String SEND_SHOW_SUSPENDED_APP_DETAILS = "android.permission.SEND_SHOW_SUSPENDED_APP_DETAILS";
     field public static final String SEND_SMS_NO_CONFIRMATION = "android.permission.SEND_SMS_NO_CONFIRMATION";
     field public static final String SERIAL_PORT = "android.permission.SERIAL_PORT";
@@ -725,6 +728,10 @@
     field public static final String ACTION_DOWNLOAD_COMPLETED = "android.intent.action.DOWNLOAD_COMPLETED";
   }
 
+  public final class GameManager {
+    method @RequiresPermission("android.permission.MANAGE_GAME_MODE") public void setGameMode(@NonNull String, int);
+  }
+
   public abstract class InstantAppResolverService extends android.app.Service {
     ctor public InstantAppResolverService();
     method public final void attachBaseContext(android.content.Context);
@@ -960,20 +967,20 @@
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public boolean getBluetoothContactSharingDisabled(@NonNull android.os.UserHandle);
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwner();
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public android.content.ComponentName getDeviceOwnerComponentOnAnyUser();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getDeviceOwnerNameOnAnyUser();
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public String getDeviceOwnerNameOnAnyUser();
     method @Nullable public CharSequence getDeviceOwnerOrganizationName();
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getDeviceOwnerUser();
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<java.lang.String> getPermittedAccessibilityServices(int);
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<java.lang.String> getPermittedInputMethodsForCurrentUser();
     method @Nullable public android.content.ComponentName getProfileOwner() throws java.lang.IllegalArgumentException;
-    method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getProfileOwnerNameAsUser(int) throws java.lang.IllegalArgumentException;
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserProvisioningState();
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public String getProfileOwnerNameAsUser(int) throws java.lang.IllegalArgumentException;
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public int getUserProvisioningState();
     method public boolean isDeviceManaged();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioned();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isDeviceProvisioningConfigApplied();
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isManagedKiosk();
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public boolean isManagedKiosk();
     method public boolean isSecondaryLockscreenEnabled(@NonNull android.os.UserHandle);
-    method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isUnattendedManagedKiosk();
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS}) public boolean isUnattendedManagedKiosk();
     method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long);
     method @RequiresPermission("android.permission.NOTIFY_PENDING_SYSTEM_UPDATE") public void notifyPendingSystemUpdate(long, boolean);
     method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public boolean packageHasActiveAdmins(String);
@@ -1999,6 +2006,8 @@
     method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean removeActiveDevice(int);
     method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean removeOnMetadataChangedListener(@NonNull android.bluetooth.BluetoothDevice, @NonNull android.bluetooth.BluetoothAdapter.OnMetadataChangedListener);
     method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean setActiveDevice(@NonNull android.bluetooth.BluetoothDevice, int);
+    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setDiscoverableTimeout(@NonNull java.time.Duration);
+    method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int setScanMode(int);
     field public static final String ACTION_BLE_STATE_CHANGED = "android.bluetooth.adapter.action.BLE_STATE_CHANGED";
     field public static final String ACTION_REQUEST_BLE_SCAN_ALWAYS_AVAILABLE = "android.bluetooth.adapter.action.REQUEST_BLE_SCAN_ALWAYS_AVAILABLE";
     field public static final int ACTIVE_DEVICE_ALL = 2; // 0x2
@@ -2015,6 +2024,13 @@
     method public void onOobData(int, @NonNull android.bluetooth.OobData);
   }
 
+  public final class BluetoothClass implements android.os.Parcelable {
+    field public static final int PROFILE_A2DP_SINK = 6; // 0x6
+    field public static final int PROFILE_NAP = 5; // 0x5
+    field public static final int PROFILE_OPP = 2; // 0x2
+    field public static final int PROFILE_PANU = 4; // 0x4
+  }
+
   public final class BluetoothCsipSetCoordinator implements java.lang.AutoCloseable android.bluetooth.BluetoothProfile {
     method @NonNull @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public java.util.List<java.lang.Integer> getAllGroupIds(@Nullable android.os.ParcelUuid);
     method @RequiresPermission(android.Manifest.permission.BLUETOOTH_PRIVILEGED) public int getConnectionPolicy(@Nullable android.bluetooth.BluetoothDevice);
@@ -2342,15 +2358,34 @@
 
 package android.companion {
 
+  public final class AssociationInfo implements android.os.Parcelable {
+    method @NonNull public String getPackageName();
+    method public boolean isSelfManaged();
+  }
+
   public final class AssociationRequest implements android.os.Parcelable {
+    method @RequiresPermission(android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED) public boolean isForceConfirmation();
+    method @RequiresPermission(android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED) public boolean isSelfManaged();
     field @RequiresPermission(android.Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING) public static final String DEVICE_PROFILE_APP_STREAMING = "android.app.role.COMPANION_DEVICE_APP_STREAMING";
     field @RequiresPermission(android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION) public static final String DEVICE_PROFILE_AUTOMOTIVE_PROJECTION = "android.app.role.SYSTEM_AUTOMOTIVE_PROJECTION";
   }
 
+  public static final class AssociationRequest.Builder {
+    method @NonNull @RequiresPermission(android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED) public android.companion.AssociationRequest.Builder setForceConfirmation(boolean);
+    method @NonNull @RequiresPermission(android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED) public android.companion.AssociationRequest.Builder setSelfManaged(boolean);
+  }
+
   public final class CompanionDeviceManager {
+    method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public void addOnAssociationsChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.OnAssociationsChangedListener);
     method @RequiresPermission(android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES) public void associate(@NonNull String, @NonNull android.net.MacAddress, @NonNull byte[]);
     method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean canPairWithoutPrompt(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
+    method @NonNull @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public java.util.List<android.companion.AssociationInfo> getAllAssociations();
     method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public boolean isDeviceAssociatedForWifiConnection(@NonNull String, @NonNull android.net.MacAddress, @NonNull android.os.UserHandle);
+    method @RequiresPermission("android.permission.MANAGE_COMPANION_DEVICES") public void removeOnAssociationsChangedListener(@NonNull android.companion.CompanionDeviceManager.OnAssociationsChangedListener);
+  }
+
+  public static interface CompanionDeviceManager.OnAssociationsChangedListener {
+    method public void onAssociationsChanged(@NonNull java.util.List<android.companion.AssociationInfo>);
   }
 
 }
@@ -2405,6 +2440,7 @@
     method @NonNull public static java.io.File encodeToFile(@NonNull android.net.Uri);
     method @Nullable @RequiresPermission("android.permission.CACHE_CONTENT") public android.os.Bundle getCache(@NonNull android.net.Uri);
     method @RequiresPermission("android.permission.CACHE_CONTENT") public void putCache(@NonNull android.net.Uri, @Nullable android.os.Bundle);
+    method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public final void registerContentObserverForAllUsers(@NonNull android.net.Uri, boolean, @NonNull android.database.ContentObserver);
   }
 
   public abstract class Context {
@@ -2435,13 +2471,14 @@
     field public static final String MEDIA_TRANSCODING_SERVICE = "media_transcoding";
     field public static final String MUSIC_RECOGNITION_SERVICE = "music_recognition";
     field public static final String NETD_SERVICE = "netd";
-    field public static final String NETWORK_SCORE_SERVICE = "network_score";
+    field @Deprecated public static final String NETWORK_SCORE_SERVICE = "network_score";
     field public static final String OEM_LOCK_SERVICE = "oem_lock";
     field public static final String PERMISSION_CONTROLLER_SERVICE = "permission_controller";
     field public static final String PERMISSION_SERVICE = "permission";
     field public static final String PERSISTENT_DATA_BLOCK_SERVICE = "persistent_data_block";
     field public static final String REBOOT_READINESS_SERVICE = "reboot_readiness";
     field public static final String ROLLBACK_SERVICE = "rollback";
+    field public static final String SAFETY_CENTER_SERVICE = "safety_center";
     field public static final String SEARCH_UI_SERVICE = "search_ui";
     field public static final String SECURE_ELEMENT_SERVICE = "secure_element";
     field public static final String SMARTSPACE_SERVICE = "smartspace";
@@ -3147,6 +3184,14 @@
 
 }
 
+package android.database {
+
+  public abstract class ContentObserver {
+    method public void onChange(boolean, @NonNull java.util.Collection<android.net.Uri>, int, @NonNull android.os.UserHandle);
+  }
+
+}
+
 package android.debug {
 
   public class AdbManager {
@@ -5097,6 +5142,7 @@
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public android.location.Location getLastKnownLocation(@NonNull String, @NonNull android.location.LastLocationRequest);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
     method public boolean isAdasGnssLocationEnabled();
+    method @RequiresPermission(android.Manifest.permission.AUTOMOTIVE_GNSS_CONTROLS) public boolean isAutoGnssSuspended();
     method public boolean isExtraLocationControllerPackageEnabled();
     method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
     method public boolean isProviderEnabledForUser(@NonNull String, @NonNull android.os.UserHandle);
@@ -5109,6 +5155,7 @@
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAdasGnssLocationEnabled(boolean);
+    method @RequiresPermission(android.Manifest.permission.AUTOMOTIVE_GNSS_CONTROLS) public void setAutoGnssSuspended(boolean);
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackage(@Nullable String);
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackageEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
@@ -6296,6 +6343,7 @@
     method public int getAudioStreamType();
     method public int getVideoStreamType();
     method public boolean isPassthrough();
+    method public boolean useSecureMemory();
     field public static final int AUDIO_STREAM_TYPE_AAC = 6; // 0x6
     field public static final int AUDIO_STREAM_TYPE_AC3 = 7; // 0x7
     field public static final int AUDIO_STREAM_TYPE_AC4 = 9; // 0x9
@@ -6331,6 +6379,7 @@
     method @NonNull public android.media.tv.tuner.filter.AvSettings build();
     method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setAudioStreamType(int);
     method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setPassthrough(boolean);
+    method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setUseSecureMemory(boolean);
     method @NonNull public android.media.tv.tuner.filter.AvSettings.Builder setVideoStreamType(int);
   }
 
@@ -6353,14 +6402,14 @@
   }
 
   public class Filter implements java.lang.AutoCloseable {
+    method @Nullable public String acquireSharedFilterToken();
     method public void close();
     method public int configure(@NonNull android.media.tv.tuner.filter.FilterConfiguration);
-    method @Nullable public String createSharedFilter();
     method public int flush();
+    method public void freeSharedFilterToken(@NonNull String);
     method @Deprecated public int getId();
     method public long getIdLong();
     method public int read(@NonNull byte[], long, long);
-    method public void releaseSharedFilter(@NonNull String);
     method public int setDataSource(@Nullable android.media.tv.tuner.filter.Filter);
     method public int setMonitorEventMask(int);
     method public int start();
@@ -6506,6 +6555,7 @@
     method public int getTsIndexMask();
     field public static final int INDEX_TYPE_NONE = 0; // 0x0
     field public static final int INDEX_TYPE_SC = 1; // 0x1
+    field public static final int INDEX_TYPE_SC_AVC = 3; // 0x3
     field public static final int INDEX_TYPE_SC_HEVC = 2; // 0x2
     field public static final int MPT_INDEX_AUDIO = 262144; // 0x40000
     field public static final int MPT_INDEX_MPT = 65536; // 0x10000
@@ -6598,6 +6648,7 @@
     method @NonNull public static android.media.tv.tuner.filter.SectionSettingsWithTableInfo.Builder builder(int);
     method public int getTableId();
     method public int getVersion();
+    field public static final int INVALID_TABLE_INFO_VERSION = -1; // 0xffffffff
   }
 
   public static class SectionSettingsWithTableInfo.Builder extends android.media.tv.tuner.filter.SectionSettings.Builder<android.media.tv.tuner.filter.SectionSettingsWithTableInfo.Builder> {
@@ -7521,7 +7572,7 @@
     method @NonNull public static android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder builder();
     method public int getCodeRate();
     method public int getModulation();
-    method @IntRange(from=0, to=255) public int getNumOfSegment();
+    method @IntRange(from=0, to=255) public int getNumberOfSegment();
     method public int getTimeInterleaveMode();
   }
 
@@ -7529,7 +7580,7 @@
     method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings build();
     method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder setCodeRate(int);
     method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder setModulation(int);
-    method @IntRange(from=0, to=255) @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder setNumOfSegment(int);
+    method @IntRange(from=0, to=255) @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder setNumberOfSegment(int);
     method @NonNull public android.media.tv.tuner.frontend.IsdbtFrontendSettings.IsdbtLayerSettings.Builder setTimeInterleaveMode(int);
   }
 
@@ -7656,15 +7707,15 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.net.MatchAllNetworkSpecifier> CREATOR;
   }
 
-  public class NetworkKey implements android.os.Parcelable {
-    ctor public NetworkKey(android.net.WifiKey);
-    method @Nullable public static android.net.NetworkKey createFromScanResult(@NonNull android.net.wifi.ScanResult);
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkKey> CREATOR;
-    field public static final int TYPE_WIFI = 1; // 0x1
-    field public final int type;
-    field public final android.net.WifiKey wifiKey;
+  @Deprecated public class NetworkKey implements android.os.Parcelable {
+    ctor @Deprecated public NetworkKey(android.net.WifiKey);
+    method @Deprecated @Nullable public static android.net.NetworkKey createFromScanResult(@NonNull android.net.wifi.ScanResult);
+    method @Deprecated public int describeContents();
+    method @Deprecated public void writeToParcel(android.os.Parcel, int);
+    field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.NetworkKey> CREATOR;
+    field @Deprecated public static final int TYPE_WIFI = 1; // 0x1
+    field @Deprecated public final int type;
+    field @Deprecated public final android.net.WifiKey wifiKey;
   }
 
   public abstract class NetworkRecommendationProvider {
@@ -7673,31 +7724,31 @@
     method public abstract void onRequestScores(android.net.NetworkKey[]);
   }
 
-  public class NetworkScoreManager {
-    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean clearScores() throws java.lang.SecurityException;
-    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public void disableScoring() throws java.lang.SecurityException;
-    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public String getActiveScorerPackage();
-    method @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public void registerNetworkScoreCallback(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkScoreManager.NetworkScoreCallback) throws java.lang.SecurityException;
-    method @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public boolean requestScores(@NonNull java.util.Collection<android.net.NetworkKey>) throws java.lang.SecurityException;
-    method @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean setActiveScorer(String) throws java.lang.SecurityException;
-    method @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(@NonNull android.net.ScoredNetwork[]) throws java.lang.SecurityException;
+  @Deprecated public class NetworkScoreManager {
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean clearScores() throws java.lang.SecurityException;
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public void disableScoring() throws java.lang.SecurityException;
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public String getActiveScorerPackage();
+    method @Deprecated @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public void registerNetworkScoreCallback(int, int, @NonNull java.util.concurrent.Executor, @NonNull android.net.NetworkScoreManager.NetworkScoreCallback) throws java.lang.SecurityException;
+    method @Deprecated @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES) public boolean requestScores(@NonNull java.util.Collection<android.net.NetworkKey>) throws java.lang.SecurityException;
+    method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.SCORE_NETWORKS, android.Manifest.permission.REQUEST_NETWORK_SCORES}) public boolean setActiveScorer(String) throws java.lang.SecurityException;
+    method @Deprecated @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS) public boolean updateScores(@NonNull android.net.ScoredNetwork[]) throws java.lang.SecurityException;
     field @Deprecated public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
-    field public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
-    field public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
-    field public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
+    field @Deprecated public static final String ACTION_CUSTOM_ENABLE = "android.net.scoring.CUSTOM_ENABLE";
+    field @Deprecated public static final String ACTION_RECOMMEND_NETWORKS = "android.net.action.RECOMMEND_NETWORKS";
+    field @Deprecated public static final String ACTION_SCORER_CHANGED = "android.net.scoring.SCORER_CHANGED";
     field @Deprecated public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
     field @Deprecated public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
-    field public static final String EXTRA_NEW_SCORER = "newScorer";
+    field @Deprecated public static final String EXTRA_NEW_SCORER = "newScorer";
     field @Deprecated public static final String EXTRA_PACKAGE_NAME = "packageName";
-    field public static final int SCORE_FILTER_CURRENT_NETWORK = 1; // 0x1
-    field public static final int SCORE_FILTER_NONE = 0; // 0x0
-    field public static final int SCORE_FILTER_SCAN_RESULTS = 2; // 0x2
+    field @Deprecated public static final int SCORE_FILTER_CURRENT_NETWORK = 1; // 0x1
+    field @Deprecated public static final int SCORE_FILTER_NONE = 0; // 0x0
+    field @Deprecated public static final int SCORE_FILTER_SCAN_RESULTS = 2; // 0x2
   }
 
-  public abstract static class NetworkScoreManager.NetworkScoreCallback {
-    ctor public NetworkScoreManager.NetworkScoreCallback();
-    method public abstract void onScoresInvalidated();
-    method public abstract void onScoresUpdated(@NonNull java.util.Collection<android.net.ScoredNetwork>);
+  @Deprecated public abstract static class NetworkScoreManager.NetworkScoreCallback {
+    ctor @Deprecated public NetworkScoreManager.NetworkScoreCallback();
+    method @Deprecated public abstract void onScoresInvalidated();
+    method @Deprecated public abstract void onScoresUpdated(@NonNull java.util.Collection<android.net.ScoredNetwork>);
   }
 
   public abstract class NetworkSpecifier {
@@ -7736,35 +7787,35 @@
     ctor public NetworkStats.Entry(@Nullable String, int, int, int, int, int, int, long, long, long, long, long);
   }
 
-  public class RssiCurve implements android.os.Parcelable {
-    ctor public RssiCurve(int, int, byte[]);
-    ctor public RssiCurve(int, int, byte[], int);
-    method public int describeContents();
-    method public byte lookupScore(int);
-    method public byte lookupScore(int, boolean);
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.RssiCurve> CREATOR;
-    field public final int activeNetworkRssiBoost;
-    field public final int bucketWidth;
-    field public final byte[] rssiBuckets;
-    field public final int start;
+  @Deprecated public class RssiCurve implements android.os.Parcelable {
+    ctor @Deprecated public RssiCurve(int, int, byte[]);
+    ctor @Deprecated public RssiCurve(int, int, byte[], int);
+    method @Deprecated public int describeContents();
+    method @Deprecated public byte lookupScore(int);
+    method @Deprecated public byte lookupScore(int, boolean);
+    method @Deprecated public void writeToParcel(android.os.Parcel, int);
+    field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.RssiCurve> CREATOR;
+    field @Deprecated public final int activeNetworkRssiBoost;
+    field @Deprecated public final int bucketWidth;
+    field @Deprecated public final byte[] rssiBuckets;
+    field @Deprecated public final int start;
   }
 
-  public class ScoredNetwork implements android.os.Parcelable {
-    ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve);
-    ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean);
-    ctor public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean, @Nullable android.os.Bundle);
-    method public int calculateBadge(int);
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final String ATTRIBUTES_KEY_BADGING_CURVE = "android.net.attributes.key.BADGING_CURVE";
-    field public static final String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL = "android.net.attributes.key.HAS_CAPTIVE_PORTAL";
-    field public static final String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET = "android.net.attributes.key.RANKING_SCORE_OFFSET";
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
-    field @Nullable public final android.os.Bundle attributes;
-    field public final boolean meteredHint;
-    field public final android.net.NetworkKey networkKey;
-    field public final android.net.RssiCurve rssiCurve;
+  @Deprecated public class ScoredNetwork implements android.os.Parcelable {
+    ctor @Deprecated public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve);
+    ctor @Deprecated public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean);
+    ctor @Deprecated public ScoredNetwork(android.net.NetworkKey, android.net.RssiCurve, boolean, @Nullable android.os.Bundle);
+    method @Deprecated public int calculateBadge(int);
+    method @Deprecated public int describeContents();
+    method @Deprecated public void writeToParcel(android.os.Parcel, int);
+    field @Deprecated public static final String ATTRIBUTES_KEY_BADGING_CURVE = "android.net.attributes.key.BADGING_CURVE";
+    field @Deprecated public static final String ATTRIBUTES_KEY_HAS_CAPTIVE_PORTAL = "android.net.attributes.key.HAS_CAPTIVE_PORTAL";
+    field @Deprecated public static final String ATTRIBUTES_KEY_RANKING_SCORE_OFFSET = "android.net.attributes.key.RANKING_SCORE_OFFSET";
+    field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.ScoredNetwork> CREATOR;
+    field @Deprecated @Nullable public final android.os.Bundle attributes;
+    field @Deprecated public final boolean meteredHint;
+    field @Deprecated public final android.net.NetworkKey networkKey;
+    field @Deprecated public final android.net.RssiCurve rssiCurve;
   }
 
   public class TrafficStats {
@@ -7791,13 +7842,13 @@
     ctor public WebAddress(String) throws android.net.ParseException;
   }
 
-  public class WifiKey implements android.os.Parcelable {
-    ctor public WifiKey(String, String);
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.net.WifiKey> CREATOR;
-    field public final String bssid;
-    field public final String ssid;
+  @Deprecated public class WifiKey implements android.os.Parcelable {
+    ctor @Deprecated public WifiKey(String, String);
+    method @Deprecated public int describeContents();
+    method @Deprecated public void writeToParcel(android.os.Parcel, int);
+    field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.net.WifiKey> CREATOR;
+    field @Deprecated public final String bssid;
+    field @Deprecated public final String ssid;
   }
 
 }
@@ -8668,6 +8719,36 @@
     method public boolean hasSingleFileDescriptor();
   }
 
+  public final class NewUserRequest {
+    method @Nullable public String getAccountName();
+    method @Nullable public android.os.PersistableBundle getAccountOptions();
+    method @Nullable public String getAccountType();
+    method @Nullable public String getName();
+    method @Nullable public android.graphics.Bitmap getUserIcon();
+    method @NonNull public String getUserType();
+    method public boolean isAdmin();
+    method public boolean isEphemeral();
+  }
+
+  public static final class NewUserRequest.Builder {
+    ctor public NewUserRequest.Builder();
+    method @NonNull public android.os.NewUserRequest build();
+    method @NonNull public android.os.NewUserRequest.Builder setAccountName(@Nullable String);
+    method @NonNull public android.os.NewUserRequest.Builder setAccountOptions(@Nullable android.os.PersistableBundle);
+    method @NonNull public android.os.NewUserRequest.Builder setAccountType(@Nullable String);
+    method @NonNull public android.os.NewUserRequest.Builder setAdmin();
+    method @NonNull public android.os.NewUserRequest.Builder setEphemeral();
+    method @NonNull public android.os.NewUserRequest.Builder setName(@Nullable String);
+    method @NonNull public android.os.NewUserRequest.Builder setUserIcon(@Nullable android.graphics.Bitmap);
+    method @NonNull public android.os.NewUserRequest.Builder setUserType(@NonNull String);
+  }
+
+  public final class NewUserResponse {
+    method public int getOperationResult();
+    method @Nullable public android.os.UserHandle getUser();
+    method public boolean isSuccessful();
+  }
+
   public interface Parcelable {
     field public static final int PARCELABLE_STABILITY_LOCAL = 0; // 0x0
     field public static final int PARCELABLE_STABILITY_VINTF = 1; // 0x1
@@ -8904,6 +8985,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean canHaveRestrictedProfile();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void clearSeedAccountData();
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle createProfile(@NonNull String, @NonNull String, @NonNull java.util.Set<java.lang.String>) throws android.os.UserManager.UserOperationException;
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.NewUserResponse createUser(@NonNull android.os.NewUserRequest);
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List<android.os.UserHandle> getAllProfiles();
     method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List<android.os.UserHandle> getEnabledProfiles();
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public android.os.UserHandle getProfileParent(@NonNull android.os.UserHandle);
@@ -8935,6 +9017,7 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean removeUser(@NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(@NonNull android.graphics.Bitmap) throws android.os.UserManager.UserOperationException;
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(@Nullable String);
+    method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public boolean someUserHasAccount(@NonNull String, @NonNull String);
     field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
     field @Deprecated public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
     field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
@@ -8946,6 +9029,8 @@
     field public static final int SWITCHABILITY_STATUS_SYSTEM_USER_LOCKED = 4; // 0x4
     field public static final int SWITCHABILITY_STATUS_USER_IN_CALL = 1; // 0x1
     field public static final int SWITCHABILITY_STATUS_USER_SWITCH_DISALLOWED = 2; // 0x2
+    field public static final int USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS = 7; // 0x7
+    field public static final String USER_TYPE_FULL_GUEST = "android.os.usertype.full.GUEST";
     field public static final String USER_TYPE_FULL_SECONDARY = "android.os.usertype.full.SECONDARY";
     field public static final String USER_TYPE_FULL_SYSTEM = "android.os.usertype.full.SYSTEM";
     field public static final String USER_TYPE_PROFILE_CLONE = "android.os.usertype.profile.CLONE";
@@ -10290,7 +10375,8 @@
     method @android.telephony.euicc.EuiccManager.OtaStatus public abstract int onGetOtaStatus(int);
     method public abstract int onRetainSubscriptionsForFactoryReset(int);
     method public abstract void onStartOtaIfNecessary(int, android.service.euicc.EuiccService.OtaStatusChangedCallback);
-    method public abstract int onSwitchToSubscription(int, @Nullable String, boolean);
+    method @Deprecated public abstract int onSwitchToSubscription(int, @Nullable String, boolean);
+    method public int onSwitchToSubscriptionWithPort(int, int, @Nullable String, boolean);
     method public abstract int onUpdateSubscriptionNickname(int, String, String);
     field public static final String ACTION_BIND_CARRIER_PROVISIONING_SERVICE = "android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE";
     field public static final String ACTION_DELETE_SUBSCRIPTION_PRIVILEGED = "android.service.euicc.action.DELETE_SUBSCRIPTION_PRIVILEGED";
@@ -10312,6 +10398,7 @@
     field public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE";
     field public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED";
     field public static final String EXTRA_RESOLUTION_CONSENT = "android.service.euicc.extra.RESOLUTION_CONSENT";
+    field public static final String EXTRA_RESOLUTION_PORT_INDEX = "android.service.euicc.extra.RESOLUTION_PORT_INDEX";
     field public static final String EXTRA_RESOLVABLE_ERRORS = "android.service.euicc.extra.RESOLVABLE_ERRORS";
     field public static final int RESOLVABLE_ERROR_CONFIRMATION_CODE = 1; // 0x1
     field public static final int RESOLVABLE_ERROR_POLICY_RULES = 2; // 0x2
@@ -12264,7 +12351,7 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEmergencyNumberDbVersion();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimDomain();
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getIsimIst();
-    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
+    method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Map<java.lang.Integer,java.lang.Integer> getLogicalToPhysicalSlotMapping();
     method public int getMaxNumberOfSimultaneouslyActiveSims();
     method public static long getMaxNumberVerificationTimeoutMillis();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String[] getMergedImsisFromGroup();
@@ -12272,10 +12359,13 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
     method public int getSimApplicationState();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int, int);
     method public int getSimCardState();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int, int);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
+    method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Collection<android.telephony.UiccSlotMapping> getSimSlotMapping();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
     method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.telephony.RadioAccessSpecifier> getSystemSelectionChannels();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
@@ -12349,6 +12439,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerState(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimPowerStateForSlot(int, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Integer>);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSimSlotMapping(@NonNull java.util.Collection<android.telephony.UiccSlotMapping>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setSystemSelectionChannels(@NonNull java.util.List<android.telephony.RadioAccessSpecifier>);
     method @Deprecated public void setVisualVoicemailEnabled(android.telecom.PhoneAccountHandle, boolean);
@@ -12360,7 +12451,7 @@
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPinReportResult(String);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean supplyPuk(String, String);
     method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int[] supplyPukReportResult(String, String);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
+    method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean switchSlots(int[]);
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void toggleRadioOnOff();
     method @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public void updateOtaEmergencyNumberDbFilePath(@NonNull android.os.ParcelFileDescriptor);
     method public void updateServiceLocation();
@@ -12530,10 +12621,11 @@
     method public int describeContents();
     method public String getCardId();
     method public int getCardStateInfo();
-    method public boolean getIsActive();
+    method @Deprecated public boolean getIsActive();
     method public boolean getIsEuicc();
     method public boolean getIsExtendedApduSupported();
-    method public int getLogicalSlotIdx();
+    method @Deprecated public int getLogicalSlotIdx();
+    method @NonNull public java.util.Collection<android.telephony.UiccPortInfo> getPorts();
     method public boolean isRemovable();
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int CARD_STATE_INFO_ABSENT = 1; // 0x1
@@ -12543,6 +12635,15 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccSlotInfo> CREATOR;
   }
 
+  public final class UiccSlotMapping implements android.os.Parcelable {
+    method public int describeContents();
+    method @IntRange(from=0) public int getLogicalSlotIndex();
+    method @IntRange(from=0) public int getPhysicalSlotIndex();
+    method @IntRange(from=0) public int getPortIndex();
+    method public void writeToParcel(@Nullable android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.UiccSlotMapping> CREATOR;
+  }
+
   public abstract class VisualVoicemailService extends android.app.Service {
     method public static final void sendVisualVoicemailSms(android.content.Context, android.telecom.PhoneAccountHandle, String, short, String, android.app.PendingIntent);
     method public static final void setSmsFilterSettings(android.content.Context, android.telecom.PhoneAccountHandle, android.telephony.VisualVoicemailSmsFilterSettings);
@@ -12834,7 +12935,8 @@
     method public void authenticateServer(String, String, byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
     method public void cancelSession(String, byte[], @android.telephony.euicc.EuiccCardManager.CancelReason int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
     method public void deleteProfile(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
-    method public void disableProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+    method @Deprecated public void disableProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
+    method public void disableProfile(@Nullable String, @Nullable String, int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
     method public void listNotifications(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
     method public void loadBoundProfilePackage(String, byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
     method public void prepareDownload(String, @Nullable byte[], byte[], byte[], byte[], java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<byte[]>);
@@ -12852,7 +12954,8 @@
     method public void retrieveNotificationList(String, @android.telephony.euicc.EuiccNotification.Event int, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.telephony.euicc.EuiccNotification[]>);
     method public void setDefaultSmdpAddress(String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
     method public void setNickname(String, String, String, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<java.lang.Void>);
-    method public void switchToProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
+    method @Deprecated public void switchToProfile(String, String, boolean, java.util.concurrent.Executor, android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
+    method public void switchToProfile(@Nullable String, @Nullable String, int, boolean, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.euicc.EuiccCardManager.ResultCallback<android.service.euicc.EuiccProfileInfo>);
     field public static final int CANCEL_REASON_END_USER_REJECTED = 0; // 0x0
     field public static final int CANCEL_REASON_POSTPONED = 1; // 0x1
     field public static final int CANCEL_REASON_PPR_NOT_ALLOWED = 3; // 0x3
@@ -13113,6 +13216,7 @@
     method @NonNull public java.util.Set<android.telephony.ims.FeatureTagState> getDeregisteredFeatureTags();
     method @NonNull public java.util.Set<android.telephony.ims.FeatureTagState> getDeregisteringFeatureTags();
     method @NonNull public java.util.Set<java.lang.String> getRegisteredFeatureTags();
+    method @NonNull public java.util.Set<java.lang.String> getRegisteringFeatureTags();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.DelegateRegistrationState> CREATOR;
     field public static final int DEREGISTERED_REASON_NOT_PROVISIONED = 1; // 0x1
@@ -13130,6 +13234,7 @@
     method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addDeregisteringFeatureTag(@NonNull String, int);
     method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addRegisteredFeatureTag(@NonNull String);
     method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addRegisteredFeatureTags(@NonNull java.util.Set<java.lang.String>);
+    method @NonNull public android.telephony.ims.DelegateRegistrationState.Builder addRegisteringFeatureTags(@NonNull java.util.Set<java.lang.String>);
     method @NonNull public android.telephony.ims.DelegateRegistrationState build();
   }
 
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index b435acf..716f43e 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -31,6 +31,10 @@
 
 
 
+MissingGetterMatchingBuilder: android.os.NewUserRequest.Builder#setAdmin():
+    android.os.NewUserRequest does not declare a `getAdmin()` method matching method android.os.NewUserRequest.Builder.setAdmin()
+MissingGetterMatchingBuilder: android.os.NewUserRequest.Builder#setEphemeral():
+    android.os.NewUserRequest does not declare a `getEphemeral()` method matching method android.os.NewUserRequest.Builder.setEphemeral()
 MissingGetterMatchingBuilder: android.security.keystore.KeyGenParameterSpec.Builder#setUid(int):
     android.security.keystore.KeyGenParameterSpec does not declare a `getUid()` method matching method android.security.keystore.KeyGenParameterSpec.Builder.setUid(int)
 MissingGetterMatchingBuilder: android.service.autofill.Dataset.Builder#setFieldInlinePresentation(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, java.util.regex.Pattern, android.service.autofill.InlinePresentation):
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index c4b2011..c1ab070 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -267,10 +267,6 @@
     method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void stopDream();
   }
 
-  public final class GameManager {
-    method @RequiresPermission("android.permission.MANAGE_GAME_MODE") public void setGameMode(@NonNull String, int);
-  }
-
   public abstract class HomeVisibilityListener {
     ctor public HomeVisibilityListener();
     method public abstract void onHomeVisibilityChanged(boolean);
@@ -1458,6 +1454,7 @@
     method public boolean hasRegisteredDynamicPolicy();
     method @RequiresPermission(anyOf={android.Manifest.permission.MODIFY_AUDIO_ROUTING, android.Manifest.permission.QUERY_AUDIO_STATE}) public boolean isFullVolumeDevice();
     method @RequiresPermission("android.permission.QUERY_AUDIO_STATE") public int requestAudioFocusForTest(@NonNull android.media.AudioFocusRequest, @NonNull String, int, int);
+    method public void setRampingRingerEnabled(boolean);
   }
 
   public static final class AudioRecord.MetricsConstants {
@@ -1834,10 +1831,6 @@
     method public int getAudioUsage();
   }
 
-  public static final class VibrationAttributes.Builder {
-    ctor public VibrationAttributes.Builder(@NonNull android.media.AudioAttributes, @Nullable android.os.VibrationEffect);
-  }
-
   public abstract class VibrationEffect implements android.os.Parcelable {
     method public static android.os.VibrationEffect get(int);
     method public static android.os.VibrationEffect get(int, boolean);
@@ -1854,13 +1847,9 @@
   }
 
   public static final class VibrationEffect.Composed extends android.os.VibrationEffect {
-    method @NonNull public android.os.VibrationEffect.Composed applyEffectStrength(int);
     method public long getDuration();
     method public int getRepeatIndex();
     method @NonNull public java.util.List<android.os.vibrator.VibrationEffectSegment> getSegments();
-    method @NonNull public android.os.VibrationEffect.Composed resolve(int);
-    method @NonNull public android.os.VibrationEffect.Composed scale(float);
-    method public void validate();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.os.VibrationEffect.Composed> CREATOR;
   }
@@ -2008,72 +1997,47 @@
 package android.os.vibrator {
 
   public final class PrebakedSegment extends android.os.vibrator.VibrationEffectSegment {
-    method @NonNull public android.os.vibrator.PrebakedSegment applyEffectStrength(int);
     method public int describeContents();
     method public long getDuration();
     method public int getEffectId();
     method public int getEffectStrength();
-    method public boolean hasNonZeroAmplitude();
-    method @NonNull public android.os.vibrator.PrebakedSegment resolve(int);
-    method @NonNull public android.os.vibrator.PrebakedSegment scale(float);
     method public boolean shouldFallback();
-    method public void validate();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.PrebakedSegment> CREATOR;
   }
 
   public final class PrimitiveSegment extends android.os.vibrator.VibrationEffectSegment {
-    method @NonNull public android.os.vibrator.PrimitiveSegment applyEffectStrength(int);
     method public int describeContents();
     method public int getDelay();
     method public long getDuration();
     method public int getPrimitiveId();
     method public float getScale();
-    method public boolean hasNonZeroAmplitude();
-    method @NonNull public android.os.vibrator.PrimitiveSegment resolve(int);
-    method @NonNull public android.os.vibrator.PrimitiveSegment scale(float);
-    method public void validate();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.PrimitiveSegment> CREATOR;
   }
 
   public final class RampSegment extends android.os.vibrator.VibrationEffectSegment {
-    method @NonNull public android.os.vibrator.RampSegment applyEffectStrength(int);
     method public int describeContents();
     method public long getDuration();
     method public float getEndAmplitude();
     method public float getEndFrequency();
     method public float getStartAmplitude();
     method public float getStartFrequency();
-    method public boolean hasNonZeroAmplitude();
-    method @NonNull public android.os.vibrator.RampSegment resolve(int);
-    method @NonNull public android.os.vibrator.RampSegment scale(float);
-    method public void validate();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.RampSegment> CREATOR;
   }
 
   public final class StepSegment extends android.os.vibrator.VibrationEffectSegment {
-    method @NonNull public android.os.vibrator.StepSegment applyEffectStrength(int);
     method public int describeContents();
     method public float getAmplitude();
     method public long getDuration();
     method public float getFrequency();
-    method public boolean hasNonZeroAmplitude();
-    method @NonNull public android.os.vibrator.StepSegment resolve(int);
-    method @NonNull public android.os.vibrator.StepSegment scale(float);
-    method public void validate();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.StepSegment> CREATOR;
   }
 
   public abstract class VibrationEffectSegment implements android.os.Parcelable {
-    method @NonNull public abstract <T extends android.os.vibrator.VibrationEffectSegment> T applyEffectStrength(int);
     method public abstract long getDuration();
-    method public abstract boolean hasNonZeroAmplitude();
-    method @NonNull public abstract <T extends android.os.vibrator.VibrationEffectSegment> T resolve(int);
-    method @NonNull public abstract <T extends android.os.vibrator.VibrationEffectSegment> T scale(float);
-    method public abstract void validate();
     field @NonNull public static final android.os.Parcelable.Creator<android.os.vibrator.VibrationEffectSegment> CREATOR;
   }
 
@@ -2193,7 +2157,7 @@
     field public static final String USER_PREFERRED_REFRESH_RATE = "user_preferred_refresh_rate";
     field public static final String USER_PREFERRED_RESOLUTION_HEIGHT = "user_preferred_resolution_height";
     field public static final String USER_PREFERRED_RESOLUTION_WIDTH = "user_preferred_resolution_width";
-    field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
+    field @Deprecated public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
   }
 
   public static final class Settings.Secure extends android.provider.Settings.NameValueTable {
@@ -3249,12 +3213,6 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.window.TaskAppearedInfo> CREATOR;
   }
 
-  public final class TaskFragmentAppearedInfo implements android.os.Parcelable {
-    method @NonNull public android.view.SurfaceControl getLeash();
-    method @NonNull public android.window.TaskFragmentInfo getTaskFragmentInfo();
-    field @NonNull public static final android.os.Parcelable.Creator<android.window.TaskFragmentAppearedInfo> CREATOR;
-  }
-
   public final class TaskFragmentCreationParams implements android.os.Parcelable {
     method @NonNull public android.os.IBinder getFragmentToken();
     method @NonNull public android.graphics.Rect getInitialBounds();
@@ -3291,7 +3249,7 @@
     ctor public TaskFragmentOrganizer(@NonNull java.util.concurrent.Executor);
     method @NonNull public java.util.concurrent.Executor getExecutor();
     method @NonNull public android.window.TaskFragmentOrganizerToken getOrganizerToken();
-    method public void onTaskFragmentAppeared(@NonNull android.window.TaskFragmentAppearedInfo);
+    method public void onTaskFragmentAppeared(@NonNull android.window.TaskFragmentInfo);
     method public void onTaskFragmentError(@NonNull android.os.IBinder, @NonNull Throwable);
     method public void onTaskFragmentInfoChanged(@NonNull android.window.TaskFragmentInfo);
     method public void onTaskFragmentParentInfoChanged(@NonNull android.os.IBinder, @NonNull android.content.res.Configuration);
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 0f852b4..09af72d 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -2071,7 +2071,7 @@
             try {
                 connection.setServiceInfo(mInfo);
                 mInfo = null;
-                AccessibilityInteractionClient.getInstance(this).clearCache();
+                AccessibilityInteractionClient.getInstance(this).clearCache(mConnectionId);
             } catch (RemoteException re) {
                 Log.w(LOG_TAG, "Error while setting AccessibilityServiceInfo", re);
                 re.rethrowFromSystemServer();
@@ -2421,7 +2421,7 @@
                     if (event != null) {
                         // Send the event to AccessibilityCache via AccessibilityInteractionClient
                         AccessibilityInteractionClient.getInstance(mContext).onAccessibilityEvent(
-                                event);
+                                event, mConnectionId);
                         if (serviceWantsEvent
                                 && (mConnectionId != AccessibilityInteractionClient.NO_ID)) {
                             // Send the event to AccessibilityService
@@ -2451,7 +2451,7 @@
                     args.recycle();
                     if (connection != null) {
                         AccessibilityInteractionClient.getInstance(mContext).addConnection(
-                                mConnectionId, connection);
+                                mConnectionId, connection, /*initializeCache=*/true);
                         if (mContext != null) {
                             try {
                                 connection.setAttributionTag(mContext.getAttributionTag());
@@ -2466,7 +2466,8 @@
                         AccessibilityInteractionClient.getInstance(mContext).removeConnection(
                                 mConnectionId);
                         mConnectionId = AccessibilityInteractionClient.NO_ID;
-                        AccessibilityInteractionClient.getInstance(mContext).clearCache();
+                        AccessibilityInteractionClient.getInstance(mContext)
+                                .clearCache(mConnectionId);
                         mCallback.init(AccessibilityInteractionClient.NO_ID, null);
                     }
                     return;
@@ -2478,7 +2479,7 @@
                     return;
                 }
                 case DO_CLEAR_ACCESSIBILITY_CACHE: {
-                    AccessibilityInteractionClient.getInstance(mContext).clearCache();
+                    AccessibilityInteractionClient.getInstance(mContext).clearCache(mConnectionId);
                     return;
                 }
                 case DO_ON_KEY_EVENT: {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt b/core/java/android/accessibilityservice/MagnificationConfig.aidl
similarity index 84%
copy from packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
copy to core/java/android/accessibilityservice/MagnificationConfig.aidl
index bacc66b..fe415a8 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
+++ b/core/java/android/accessibilityservice/MagnificationConfig.aidl
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.flags
+package android.accessibilityservice;
 
-interface FlagWriter {
-    fun setEnabled(key: Int, value: Boolean) {}
-}
\ No newline at end of file
+parcelable MagnificationConfig;
diff --git a/core/java/android/accessibilityservice/MagnificationConfig.java b/core/java/android/accessibilityservice/MagnificationConfig.java
new file mode 100644
index 0000000..8884508
--- /dev/null
+++ b/core/java/android/accessibilityservice/MagnificationConfig.java
@@ -0,0 +1,250 @@
+/*
+ * Copyright (C) 2021 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 android.accessibilityservice;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class describes the magnification config for {@link AccessibilityService} to control the
+ * magnification.
+ *
+ * <p>
+ * When the magnification config uses {@link #DEFAULT_MODE},
+ * {@link AccessibilityService} will be able to control the activated magnifier on the display.
+ * If there is no magnifier activated, it controls the last-activated magnification mode.
+ * If there is no magnifier activated before, it controls full-screen magnifier by default.
+ * </p>
+ *
+ * <p>
+ * When the magnification config uses {@link #FULLSCREEN_MODE}. {@link AccessibilityService} will
+ * be able to control full-screen magnifier on the display.
+ * </p>
+ *
+ * <p>
+ * When the magnification config uses {@link #WINDOW_MODE}. {@link AccessibilityService} will be
+ * able to control the activated window magnifier on the display.
+ * </p>
+ *
+ * <p>
+ * If the other magnification configs, scale centerX and centerY, are not set by the
+ * {@link Builder}, the configs should be current values or default values. And the center
+ * position ordinarily is the center of the screen.
+ * </p>
+ */
+public final class MagnificationConfig implements Parcelable {
+
+    /** The controlling magnification mode. It controls the activated magnifier. */
+    public static final int DEFAULT_MODE = 0;
+    /** The controlling magnification mode. It controls fullscreen magnifier. */
+    public static final int FULLSCREEN_MODE = 1;
+    /** The controlling magnification mode. It controls window magnifier. */
+    public static final int WINDOW_MODE = 2;
+
+    @IntDef(prefix = {"MAGNIFICATION_MODE"}, value = {
+            DEFAULT_MODE,
+            FULLSCREEN_MODE,
+            WINDOW_MODE,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface MAGNIFICATION_MODE {
+    }
+
+    private int mMode = DEFAULT_MODE;
+    private float mScale = Float.NaN;
+    private float mCenterX = Float.NaN;
+    private float mCenterY = Float.NaN;
+
+    private MagnificationConfig() {
+        /* do nothing */
+    }
+
+    private MagnificationConfig(@NonNull Parcel parcel) {
+        mMode = parcel.readInt();
+        mScale = parcel.readFloat();
+        mCenterX = parcel.readFloat();
+        mCenterY = parcel.readFloat();
+    }
+
+    /**
+     * Returns the magnification mode that is the current activated mode or the controlling mode of
+     * the config.
+     *
+     * @return The magnification mode
+     */
+    public int getMode() {
+        return mMode;
+    }
+
+    /**
+     * Returns the magnification scale of the controlling magnifier
+     *
+     * @return the scale If the controlling magnifier is not activated, it returns 1 by default
+     */
+    public float getScale() {
+        return mScale;
+    }
+
+    /**
+     * Returns the screen-relative X coordinate of the center of the magnification viewport.
+     *
+     * @return the X coordinate. If the controlling magnifier is {@link #WINDOW_MODE} but not
+     * enabled, it returns {@link Float#NaN}. If the controlling magnifier is {@link
+     * #FULLSCREEN_MODE} but not enabled, it returns 0
+     */
+    public float getCenterX() {
+        return mCenterX;
+    }
+
+    /**
+     * Returns the screen-relative Y coordinate of the center of the magnification viewport.
+     *
+     * @return the Y coordinate If the controlling magnifier is {@link #WINDOW_MODE} but not
+     * enabled, it returns {@link Float#NaN}. If the controlling magnifier is {@link
+     * #FULLSCREEN_MODE} but not enabled, it returns 0
+     */
+    public float getCenterY() {
+        return mCenterY;
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        StringBuilder stringBuilder = new StringBuilder("MagnificationConfig[");
+        stringBuilder.append("mode: ").append(getMode());
+        stringBuilder.append(", ");
+        stringBuilder.append("scale: ").append(getScale());
+        stringBuilder.append(", ");
+        stringBuilder.append("centerX: ").append(getCenterX());
+        stringBuilder.append(", ");
+        stringBuilder.append("centerY: ").append(getCenterY());
+        stringBuilder.append("] ");
+        return stringBuilder.toString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel parcel, int flags) {
+        parcel.writeInt(mMode);
+        parcel.writeFloat(mScale);
+        parcel.writeFloat(mCenterX);
+        parcel.writeFloat(mCenterY);
+    }
+
+    /**
+     * Builder for creating {@link MagnificationConfig} objects.
+     */
+    public static final class Builder {
+
+        private int mMode = DEFAULT_MODE;
+        private float mScale = Float.NaN;
+        private float mCenterX = Float.NaN;
+        private float mCenterY = Float.NaN;
+
+        /**
+         * Creates a new Builder.
+         */
+        public Builder() {
+        }
+
+        /**
+         * Sets the magnification mode.
+         *
+         * @param mode The magnification mode
+         * @return This builder
+         */
+        @NonNull
+        public MagnificationConfig.Builder setMode(@MAGNIFICATION_MODE int mode) {
+            mMode = mode;
+            return this;
+        }
+
+        /**
+         * Sets the magnification scale.
+         *
+         * @param scale The magnification scale
+         * @return This builder
+         */
+        @NonNull
+        public MagnificationConfig.Builder setScale(float scale) {
+            mScale = scale;
+            return this;
+        }
+
+        /**
+         * Sets the X coordinate of the center of the magnification viewport.
+         *
+         * @param centerX the screen-relative X coordinate around which to
+         *                center and scale, or {@link Float#NaN} to leave unchanged
+         * @return This builder
+         */
+        @NonNull
+        public MagnificationConfig.Builder setCenterX(float centerX) {
+            mCenterX = centerX;
+            return this;
+        }
+
+        /**
+         * Sets the Y coordinate of the center of the magnification viewport.
+         *
+         * @param centerY the screen-relative Y coordinate around which to
+         *                center and scale, or {@link Float#NaN} to leave unchanged
+         * @return This builder
+         */
+        @NonNull
+        public MagnificationConfig.Builder setCenterY(float centerY) {
+            mCenterY = centerY;
+            return this;
+        }
+
+        /**
+         * Builds and returns a {@link MagnificationConfig}
+         */
+        @NonNull
+        public MagnificationConfig build() {
+            MagnificationConfig magnificationConfig = new MagnificationConfig();
+            magnificationConfig.mMode = mMode;
+            magnificationConfig.mScale = mScale;
+            magnificationConfig.mCenterX = mCenterX;
+            magnificationConfig.mCenterY = mCenterY;
+            return magnificationConfig;
+        }
+    }
+
+    /**
+     * @see Parcelable.Creator
+     */
+    public static final @NonNull Parcelable.Creator<MagnificationConfig> CREATOR =
+            new Parcelable.Creator<MagnificationConfig>() {
+                public MagnificationConfig createFromParcel(Parcel parcel) {
+                    return new MagnificationConfig(parcel);
+                }
+
+                public MagnificationConfig[] newArray(int size) {
+                    return new MagnificationConfig[size];
+                }
+            };
+}
diff --git a/core/java/android/accessibilityservice/TouchInteractionController.java b/core/java/android/accessibilityservice/TouchInteractionController.java
index d9be49a..a8ba1d3 100644
--- a/core/java/android/accessibilityservice/TouchInteractionController.java
+++ b/core/java/android/accessibilityservice/TouchInteractionController.java
@@ -100,8 +100,8 @@
     private final Object mLock;
     private final int mDisplayId;
     private boolean mServiceDetectsGestures;
-    /** Map of listeners to executors. Lazily created when adding the first listener. */
-    private ArrayMap<Listener, Executor> mListeners;
+    /** Map of callbacks to executors. Lazily created when adding the first callback. */
+    private ArrayMap<Callback, Executor> mCallbacks;
 
     // The current state of the display.
     private int mState = STATE_CLEAR;
@@ -114,38 +114,38 @@
     }
 
     /**
-     * Adds the specified change listener to the list of motion event listeners. The callback will
+     * Adds the specified callback to the list of callbacks. The callback will
      * run using on the specified {@link Executor}', or on the service's main thread if the
      * Executor is {@code null}.
-     * @param listener the listener to add, must be non-null
+     * @param callback the callback to add, must be non-null
      * @param executor the executor for this callback, or {@code null} to execute on the service's
      *     main thread
      */
-    public void addListener(@Nullable Executor executor, @NonNull Listener listener) {
+    public void registerCallback(@Nullable Executor executor, @NonNull Callback callback) {
         synchronized (mLock) {
-            if (mListeners == null) {
-                mListeners = new ArrayMap<>();
+            if (mCallbacks == null) {
+                mCallbacks = new ArrayMap<>();
             }
-            mListeners.put(listener, executor);
-            if (mListeners.size() == 1) {
+            mCallbacks.put(callback, executor);
+            if (mCallbacks.size() == 1) {
                 setServiceDetectsGestures(true);
             }
         }
     }
 
     /**
-     * Removes the specified listener from the list of motion event listeners.
+     * Unregisters the specified callback.
      *
-     * @param listener the listener to remove, must be non-null
-     * @return {@code true} if the listener was removed, {@code false} otherwise
+     * @param callback the callback to remove, must be non-null
+     * @return {@code true} if the callback was removed, {@code false} otherwise
      */
-    public boolean removeListener(@NonNull Listener listener) {
-        if (mListeners == null) {
+    public boolean unregisterCallback(@NonNull Callback callback) {
+        if (mCallbacks == null) {
             return false;
         }
         synchronized (mLock) {
-            boolean result = mListeners.remove(listener) != null;
-            if (result && mListeners.size() == 0) {
+            boolean result = mCallbacks.remove(callback) != null;
+            if (result && mCallbacks.size() == 0) {
                 setServiceDetectsGestures(false);
             }
             return result;
@@ -153,60 +153,60 @@
     }
 
     /**
-     * Removes all listeners and returns control of touch interactions to the framework.
+     * Removes all callbacks and returns control of touch interactions to the framework.
      */
-    public void removeAllListeners() {
-        if (mListeners != null) {
+    public void unregisterAllCallbacks() {
+        if (mCallbacks != null) {
             synchronized (mLock) {
-                mListeners.clear();
+                mCallbacks.clear();
                 setServiceDetectsGestures(false);
             }
         }
     }
 
     /**
-     * Dispatches motion events to any registered listeners. This should be called on the service's
+     * Dispatches motion events to any registered callbacks. This should be called on the service's
      * main thread.
      */
     void onMotionEvent(MotionEvent event) {
-        final ArrayMap<Listener, Executor> entries;
+        final ArrayMap<Callback, Executor> entries;
         synchronized (mLock) {
-            // Listeners may remove themselves. Perform a shallow copy to avoid concurrent
+            // callbacks may remove themselves. Perform a shallow copy to avoid concurrent
             // modification.
-            entries = new ArrayMap<>(mListeners);
+            entries = new ArrayMap<>(mCallbacks);
         }
         for (int i = 0, count = entries.size(); i < count; i++) {
-            final Listener listener = entries.keyAt(i);
+            final Callback callback = entries.keyAt(i);
             final Executor executor = entries.valueAt(i);
             if (executor != null) {
-                executor.execute(() -> listener.onMotionEvent(event));
+                executor.execute(() -> callback.onMotionEvent(event));
             } else {
-                // We're already on the main thread, just run the listener.
-                listener.onMotionEvent(event);
+                // We're already on the main thread, just run the callback.
+                callback.onMotionEvent(event);
             }
         }
     }
 
     /**
-     * Dispatches motion events to any registered listeners. This should be called on the service's
+     * Dispatches motion events to any registered callbacks. This should be called on the service's
      * main thread.
      */
     void onStateChanged(@State int state) {
         mState = state;
-        final ArrayMap<Listener, Executor> entries;
+        final ArrayMap<Callback, Executor> entries;
         synchronized (mLock) {
-            // Listeners may remove themselves. Perform a shallow copy to avoid concurrent
+            // callbacks may remove themselves. Perform a shallow copy to avoid concurrent
             // modification.
-            entries = new ArrayMap<>(mListeners);
+            entries = new ArrayMap<>(mCallbacks);
         }
         for (int i = 0, count = entries.size(); i < count; i++) {
-            final Listener listener = entries.keyAt(i);
+            final Callback callback = entries.keyAt(i);
             final Executor executor = entries.valueAt(i);
             if (executor != null) {
-                executor.execute(() -> listener.onStateChanged(state));
+                executor.execute(() -> callback.onStateChanged(state));
             } else {
-                // We're already on the main thread, just run the listener.
-                listener.onStateChanged(state);
+                // We're already on the main thread, just run the callback.
+                callback.onStateChanged(state);
             }
         }
     }
@@ -238,7 +238,7 @@
 
     /**
      * If {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled and at
-     * least one listener has been added for this display this function tells the framework to
+     * least one callback has been added for this display this function tells the framework to
      * initiate touch exploration. Touch exploration will continue for the duration of this
      * interaction.
      */
@@ -259,7 +259,7 @@
     /**
      * If {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} and {@link If
      * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled and at least
-     * one listener has been added, this function tells the framework to initiate a dragging
+     * one callback has been added, this function tells the framework to initiate a dragging
      * interaction using the specified pointer. The pointer's movements will be passed through to
      * the rest of the input pipeline. Dragging is often used to perform two-finger scrolling.
      *
@@ -287,7 +287,7 @@
     /**
      * If {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} and {@link If
      * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled and at least
-     * one listener has been added, this function tells the framework to initiate a delegating
+     * one callback has been added, this function tells the framework to initiate a delegating
      * interaction. Motion events will be passed through as-is to the rest of the input pipeline for
      * the duration of this interaction.
      */
@@ -308,7 +308,7 @@
     /**
      * If {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} and {@link If
      * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled and at least
-     * one listener has been added, this function tells the framework to perform a click.
+     * one callback has been added, this function tells the framework to perform a click.
      * The framework will first try to perform
      * {@link AccessibilityNodeInfo.AccessibilityAction#ACTION_CLICK} on the item with
      * accessibility focus. If that fails, the framework will simulate a click using motion events
@@ -330,7 +330,7 @@
     /**
      * If {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} and {@link If
      * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled and at least
-     * one listener has been added, this function tells the framework to perform a long click.
+     * one callback has been added, this function tells the framework to perform a long click.
      * The framework will simulate a long click using motion events on the last location with
      * accessibility focus and will delegate any movements to the rest of the input pipeline. This
      * allows a user to double-tap and hold to trigger a drag and then execute that drag by moving
@@ -350,9 +350,9 @@
     }
 
     private void checkState() {
-        if (!mServiceDetectsGestures || mListeners.size() == 0) {
+        if (!mServiceDetectsGestures || mCallbacks.size() == 0) {
             throw new IllegalStateException(
-                    "State transitions are not allowed without first adding a listener.");
+                    "State transitions are not allowed without first adding a callback.");
         }
         if (mState != STATE_TOUCH_INTERACTING) {
             throw new IllegalStateException(
@@ -402,8 +402,8 @@
         }
     }
 
-    /** Listeners allow services to receive motion events and state change updates. */
-    public interface Listener {
+    /** callbacks allow services to receive motion events and state change updates. */
+    public interface Callback {
         /**
          * Called when the framework has sent a motion event to the service.
          *
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index f9cc323..9f8d246 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -4082,6 +4082,34 @@
     }
 
     /**
+     * Gets the message that is shown when a user is switched from.
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MANAGE_USERS)
+    public @Nullable String getSwitchingFromUserMessage() {
+        try {
+            return getService().getSwitchingFromUserMessage();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Gets the message that is shown when a user is switched to.
+     *
+     * @hide
+     */
+    @RequiresPermission(Manifest.permission.MANAGE_USERS)
+    public @Nullable String getSwitchingToUserMessage() {
+        try {
+            return getService().getSwitchingToUserMessage();
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Uses the value defined by the platform.
      *
      * @hide
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 19223f9..e420b7d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -29,6 +29,7 @@
 import static android.app.servertransaction.ActivityLifecycleItem.PRE_ON_CREATE;
 import static android.content.ContentResolver.DEPRECATE_DATA_COLUMNS;
 import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.window.ConfigurationHelper.diffPublicWithSizeBuckets;
 import static android.window.ConfigurationHelper.freeTextLayoutCachesIfNeeded;
@@ -37,8 +38,16 @@
 
 import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
 
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UptimeMillisLong;
+import android.app.RemoteServiceException.BadForegroundServiceNotificationException;
+import android.app.RemoteServiceException.CannotDeliverBroadcastException;
+import android.app.RemoteServiceException.CannotPostForegroundServiceNotificationException;
+import android.app.RemoteServiceException.CrashedByAdbException;
+import android.app.RemoteServiceException.ForegroundServiceDidNotStartInTimeException;
+import android.app.RemoteServiceException.MissingRequestPasswordComplexityPermissionException;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.app.backup.BackupAgent;
@@ -314,7 +323,7 @@
 
     @UnsupportedAppUsage
     private ContextImpl mSystemContext;
-    private ContextImpl mSystemUiContext;
+    private final SparseArray<ContextImpl> mDisplaySystemUiContexts = new SparseArray<>();
 
     @UnsupportedAppUsage
     static volatile IPackageManager sPackageManager;
@@ -888,6 +897,9 @@
 
         SharedMemory mSerializedSystemFontMap;
 
+        long startRequestedElapsedTime;
+        long startRequestedUptime;
+
         @Override
         public String toString() {
             return "AppBindData{appInfo=" + appInfo + "}";
@@ -1099,7 +1111,8 @@
                 CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                 String buildSerial, AutofillOptions autofillOptions,
                 ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges,
-                SharedMemory serializedSystemFontMap) {
+                SharedMemory serializedSystemFontMap,
+                long startRequestedElapsedTime, long startRequestedUptime) {
             if (services != null) {
                 if (false) {
                     // Test code to make sure the app could see the passed-in services.
@@ -1149,6 +1162,8 @@
             data.contentCaptureOptions = contentCaptureOptions;
             data.disabledCompatChanges = disabledCompatChanges;
             data.mSerializedSystemFontMap = serializedSystemFontMap;
+            data.startRequestedElapsedTime = startRequestedElapsedTime;
+            data.startRequestedUptime = startRequestedUptime;
             sendMessage(H.BIND_APPLICATION, data);
         }
 
@@ -1921,11 +1936,27 @@
     private void throwRemoteServiceException(String message, int typeId) {
         // Use a switch to ensure all the type IDs are unique.
         switch (typeId) {
-            case ForegroundServiceDidNotStartInTimeException.TYPE_ID: // 1
+            case ForegroundServiceDidNotStartInTimeException.TYPE_ID:
                 throw new ForegroundServiceDidNotStartInTimeException(message);
-            case RemoteServiceException.TYPE_ID: // 0
+
+            case CannotDeliverBroadcastException.TYPE_ID:
+                throw new CannotDeliverBroadcastException(message);
+
+            case CannotPostForegroundServiceNotificationException.TYPE_ID:
+                throw new CannotPostForegroundServiceNotificationException(message);
+
+            case BadForegroundServiceNotificationException.TYPE_ID:
+                throw new BadForegroundServiceNotificationException(message);
+
+            case MissingRequestPasswordComplexityPermissionException.TYPE_ID:
+                throw new MissingRequestPasswordComplexityPermissionException(message);
+
+            case CrashedByAdbException.TYPE_ID:
+                throw new CrashedByAdbException(message);
+
             default:
-                throw new RemoteServiceException(message);
+                throw new RemoteServiceException(message
+                        + " (with unwknown typeId:" + typeId + ")");
         }
     }
 
@@ -2611,22 +2642,26 @@
     }
 
     @Override
+    @NonNull
     public ContextImpl getSystemUiContext() {
-        synchronized (this) {
-            if (mSystemUiContext == null) {
-                mSystemUiContext = ContextImpl.createSystemUiContext(getSystemContext());
-            }
-            return mSystemUiContext;
-        }
+        return getSystemUiContext(DEFAULT_DISPLAY);
     }
 
     /**
-     * Create the context instance base on system resources & display information which used for UI.
+     * Gets the context instance base on system resources & display information which used for UI.
      * @param displayId The ID of the display where the UI is shown.
      * @see ContextImpl#createSystemUiContext(ContextImpl, int)
      */
-    public ContextImpl createSystemUiContext(int displayId) {
-        return ContextImpl.createSystemUiContext(getSystemUiContext(), displayId);
+    @NonNull
+    public ContextImpl getSystemUiContext(int displayId) {
+        synchronized (this) {
+            ContextImpl systemUiContext = mDisplaySystemUiContexts.get(displayId);
+            if (systemUiContext == null) {
+                systemUiContext = ContextImpl.createSystemUiContext(getSystemContext(), displayId);
+                mDisplaySystemUiContexts.put(displayId, systemUiContext);
+            }
+            return systemUiContext;
+        }
     }
 
     public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
@@ -3745,7 +3780,7 @@
         if (pkgName != null && !pkgName.isEmpty()
                 && r.packageInfo.mPackageName.contains(pkgName)) {
             for (int id : dm.getDisplayIds()) {
-                if (id != Display.DEFAULT_DISPLAY) {
+                if (id != DEFAULT_DISPLAY) {
                     Display display =
                             dm.getCompatibleDisplay(id, appContext.getResources());
                     appContext = (ContextImpl) appContext.createDisplayContext(display);
@@ -6407,7 +6442,8 @@
             DdmVmInternal.setRecentAllocationsTrackingEnabled(true);
         }
         // Note when this process has started.
-        Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
+        Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis(),
+                data.startRequestedElapsedTime, data.startRequestedUptime);
 
         AppCompatCallbacks.install(data.disabledCompatChanges);
         // Let libcore handle any compat changes after installing the list of compat changes.
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 7a545f6..565f690 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -9469,23 +9469,23 @@
                     e.rethrowFromSystemServer();
                 }
 
-                if (missedAsyncOps != null) {
+                // Copy pointer so callback can be dispatched out of lock
+                OnOpNotedCallback onOpNotedCallback = sOnOpNotedCallback;
+                if (onOpNotedCallback != null && missedAsyncOps != null) {
                     int numMissedAsyncOps = missedAsyncOps.size();
                     for (int i = 0; i < numMissedAsyncOps; i++) {
                         final AsyncNotedAppOp asyncNotedAppOp = missedAsyncOps.get(i);
-                        if (sOnOpNotedCallback != null) {
-                            sOnOpNotedCallback.getAsyncNotedExecutor().execute(
-                                    () -> sOnOpNotedCallback.onAsyncNoted(asyncNotedAppOp));
-                        }
+                        onOpNotedCallback.getAsyncNotedExecutor().execute(
+                                () -> onOpNotedCallback.onAsyncNoted(asyncNotedAppOp));
                     }
                 }
                 synchronized (this) {
                     int numMissedSyncOps = sUnforwardedOps.size();
-                    for (int i = 0; i < numMissedSyncOps; i++) {
-                        final AsyncNotedAppOp syncNotedAppOp = sUnforwardedOps.get(i);
-                        if (sOnOpNotedCallback != null) {
-                            sOnOpNotedCallback.getAsyncNotedExecutor().execute(
-                                    () -> sOnOpNotedCallback.onAsyncNoted(syncNotedAppOp));
+                    if (onOpNotedCallback != null) {
+                        for (int i = 0; i < numMissedSyncOps; i++) {
+                            final AsyncNotedAppOp syncNotedAppOp = sUnforwardedOps.get(i);
+                            onOpNotedCallback.getAsyncNotedExecutor().execute(
+                                    () -> onOpNotedCallback.onAsyncNoted(syncNotedAppOp));
                         }
                     }
                     sUnforwardedOps.clear();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 1943f9d..d1b7145 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -920,16 +920,16 @@
         Objects.requireNonNull(packageName);
         Objects.requireNonNull(onChecksumsReadyListener);
         Objects.requireNonNull(trustedInstallers);
+        if (trustedInstallers == TRUST_ALL) {
+            trustedInstallers = null;
+        } else if (trustedInstallers == TRUST_NONE) {
+            trustedInstallers = Collections.emptyList();
+        } else if (trustedInstallers.isEmpty()) {
+            throw new IllegalArgumentException(
+                    "trustedInstallers has to be one of TRUST_ALL/TRUST_NONE or a non-empty "
+                            + "list of certificates.");
+        }
         try {
-            if (trustedInstallers == TRUST_ALL) {
-                trustedInstallers = null;
-            } else if (trustedInstallers == TRUST_NONE) {
-                trustedInstallers = Collections.emptyList();
-            } else if (trustedInstallers.isEmpty()) {
-                throw new IllegalArgumentException(
-                        "trustedInstallers has to be one of TRUST_ALL/TRUST_NONE or a non-empty "
-                                + "list of certificates.");
-            }
             IOnChecksumsReadyListener onChecksumsReadyListenerDelegate =
                     new IOnChecksumsReadyListener.Stub() {
                         @Override
@@ -938,7 +938,7 @@
                             onChecksumsReadyListener.onChecksumsReady(checksums);
                         }
                     };
-            mPM.requestChecksums(packageName, includeSplits, DEFAULT_CHECKSUMS, required,
+            mPM.requestPackageChecksums(packageName, includeSplits, DEFAULT_CHECKSUMS, required,
                     encodeCertificates(trustedInstallers), onChecksumsReadyListenerDelegate,
                     getUserId());
         } catch (ParcelableException e) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 756833a..9d5e971 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2638,7 +2638,10 @@
                 overrideConfig, display.getDisplayAdjustments().getCompatibilityInfo(),
                 mResources.getLoaders()));
         context.mDisplay = display;
-        context.mContextType = CONTEXT_TYPE_DISPLAY_CONTEXT;
+        // Inherit context type if the container is from System or System UI context to bypass
+        // UI context check.
+        context.mContextType = mContextType == CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI
+                ? CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI : CONTEXT_TYPE_DISPLAY_CONTEXT;
         // Display contexts and any context derived from a display context should always override
         // the display that would otherwise be inherited from mToken (or the global configuration if
         // mToken is null).
@@ -2691,7 +2694,8 @@
 
         // Step 2. Create the base context of the window context, it will also create a Resources
         //         associated with the WindowTokenClient and set the token to the base context.
-        final ContextImpl windowContextBase = createWindowContextBase(windowTokenClient, display);
+        final ContextImpl windowContextBase = createWindowContextBase(windowTokenClient,
+                display.getDisplayId());
 
         // Step 3. Create a WindowContext instance and set it as the outer context of the base
         //         context to make the service obtained by #getSystemService(String) able to query
@@ -2716,9 +2720,7 @@
         if (display == null) {
             throw new IllegalArgumentException("Display must not be null");
         }
-        final ContextImpl tokenContext = createWindowContextBase(token, display);
-        tokenContext.setResources(createWindowContextResources(tokenContext));
-        return tokenContext;
+        return createWindowContextBase(token, display.getDisplayId());
     }
 
     /**
@@ -2726,13 +2728,13 @@
      * window.
      *
      * @param token The token to associate with {@link Resources}
-     * @param display The {@link Display} to associate with.
+     * @param displayId The ID of {@link Display} to associate with.
      *
      * @see #createWindowContext(Display, int, Bundle)
      * @see #createTokenContext(IBinder, Display)
      */
     @UiContext
-    ContextImpl createWindowContextBase(@NonNull IBinder token, @NonNull Display display) {
+    ContextImpl createWindowContextBase(@NonNull IBinder token, int displayId) {
         ContextImpl baseContext = new ContextImpl(this, mMainThread, mPackageInfo, mParams,
                 mAttributionSource.getAttributionTag(),
                 mAttributionSource.getNext(),
@@ -2746,8 +2748,8 @@
         baseContext.setResources(windowContextResources);
         // Associate the display with window context resources so that configuration update from
         // the server side will also apply to the display's metrics.
-        baseContext.mDisplay = ResourcesManager.getInstance()
-                .getAdjustedDisplay(display.getDisplayId(), windowContextResources);
+        baseContext.mDisplay = ResourcesManager.getInstance().getAdjustedDisplay(displayId,
+                windowContextResources);
 
         return baseContext;
     }
@@ -2983,6 +2985,18 @@
         mContentCaptureOptions = options;
     }
 
+    @Override
+    protected void finalize() throws Throwable {
+        // If mToken is a WindowTokenClient, the Context is usually associated with a
+        // WindowContainer. We should detach from WindowContainer when the Context is finalized
+        // if this Context is not a WindowContext. WindowContext finalization is handled in
+        // WindowContext class.
+        if (mToken instanceof WindowTokenClient && mContextType != CONTEXT_TYPE_WINDOW_CONTEXT) {
+            ((WindowTokenClient) mToken).detachFromWindowContainerIfNeeded();
+        }
+        super.finalize();
+    }
+
     @UnsupportedAppUsage
     static ContextImpl createSystemContext(ActivityThread mainThread) {
         LoadedApk packageInfo = new LoadedApk(mainThread);
@@ -3003,22 +3017,13 @@
      * @param displayId The ID of the display where the UI is shown.
      */
     static ContextImpl createSystemUiContext(ContextImpl systemContext, int displayId) {
-        final LoadedApk packageInfo = systemContext.mPackageInfo;
-        ContextImpl context = new ContextImpl(null, systemContext.mMainThread, packageInfo,
-                ContextParams.EMPTY, null, null, null, null, null, 0, null, null);
-        context.setResources(createResources(null, packageInfo, null, displayId, null,
-                packageInfo.getCompatibilityInfo(), null));
-        context.updateDisplay(displayId);
+        final WindowTokenClient token = new WindowTokenClient();
+        final ContextImpl context = systemContext.createWindowContextBase(token, displayId);
+        token.attachContext(context);
+        token.attachToDisplayContent(displayId);
         context.mContextType = CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI;
-        return context;
-    }
 
-    /**
-     * The overloaded method of {@link #createSystemUiContext(ContextImpl, int)}.
-     * Uses {@Code Display.DEFAULT_DISPLAY} as the target display.
-     */
-    static ContextImpl createSystemUiContext(ContextImpl systemContext) {
-        return createSystemUiContext(systemContext, Display.DEFAULT_DISPLAY);
+        return context;
     }
 
     @UnsupportedAppUsage
@@ -3227,7 +3232,13 @@
 
     @Override
     public IBinder getWindowContextToken() {
-        return mContextType == CONTEXT_TYPE_WINDOW_CONTEXT ? mToken : null;
+        switch (mContextType) {
+            case CONTEXT_TYPE_WINDOW_CONTEXT:
+            case CONTEXT_TYPE_SYSTEM_OR_SYSTEM_UI:
+                return mToken;
+            default:
+                return null;
+        }
     }
 
     private void checkMode(int mode) {
diff --git a/core/java/android/app/ForegroundServiceDidNotStartInTimeException.java b/core/java/android/app/ForegroundServiceDidNotStartInTimeException.java
deleted file mode 100644
index 364291e..0000000
--- a/core/java/android/app/ForegroundServiceDidNotStartInTimeException.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2021 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 android.app;
-
-/**
- * Exception used to crash an app process when it didn't call {@link Service#startForeground}
- * in time after the service was started with
- * {@link android.content.Context#startForegroundService}.
- *
- * @hide
- */
-public class ForegroundServiceDidNotStartInTimeException extends RemoteServiceException {
-    /** The type ID passed to {@link IApplicationThread#scheduleCrash}. */
-    public static final int TYPE_ID = 1;
-
-    public ForegroundServiceDidNotStartInTimeException(String msg) {
-        super(msg);
-    }
-}
diff --git a/core/java/android/app/GameManager.java b/core/java/android/app/GameManager.java
index b324fb6..78759db 100644
--- a/core/java/android/app/GameManager.java
+++ b/core/java/android/app/GameManager.java
@@ -21,8 +21,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.annotation.TestApi;
 import android.annotation.UserHandleAware;
 import android.content.Context;
 import android.os.Handler;
@@ -125,7 +125,7 @@
      *
      * @hide
      */
-    @TestApi
+    @SystemApi
     @UserHandleAware
     @RequiresPermission(Manifest.permission.MANAGE_GAME_MODE)
     public void setGameMode(@NonNull String packageName, @GameMode int gameMode) {
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 853d5e8..183e714 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -330,8 +330,6 @@
     void handleApplicationStrictModeViolation(in IBinder app, int penaltyMask,
             in StrictMode.ViolationInfo crashInfo);
     boolean isTopActivityImmersive();
-    void crashApplication(int uid, int initialPid, in String packageName, int userId,
-            in String message, boolean force);
     void crashApplicationWithType(int uid, int initialPid, in String packageName, int userId,
             in String message, boolean force, int exceptionTypeId);
     /** @deprecated -- use getProviderMimeTypeAsync */
@@ -351,6 +349,8 @@
     void setPackageScreenCompatMode(in String packageName, int mode);
     @UnsupportedAppUsage
     boolean switchUser(int userid);
+    String getSwitchingFromUserMessage();
+    String getSwitchingToUserMessage();
     @UnsupportedAppUsage
     void setStopUserOnSwitch(int value);
     boolean removeTask(int taskId);
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index d6ff6d3..0e42a79 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -80,7 +80,8 @@
             in CompatibilityInfo compatInfo, in Map services,
             in Bundle coreSettings, in String buildSerial, in AutofillOptions autofillOptions,
             in ContentCaptureOptions contentCaptureOptions, in long[] disabledCompatChanges,
-            in SharedMemory serializedSystemFontMap);
+            in SharedMemory serializedSystemFontMap,
+            long startRequestedElapsedTime, long startRequestedUptime);
     void runIsolatedEntryPoint(in String entryPoint, in String[] entryPointArgs);
     void scheduleExit();
     void scheduleServiceArgs(IBinder token, in ParceledListSlice args);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 6bfde9a..af907af 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6791,7 +6791,7 @@
 
         // We show these sorts of notifications immediately in the absence of
         // any explicit app declaration
-        if (isMediaNotification() || hasMediaSession()
+        if (isMediaNotification()
                     || CATEGORY_CALL.equals(category)
                     || CATEGORY_NAVIGATION.equals(category)
                     || (actions != null && actions.length > 0)) {
@@ -6811,14 +6811,6 @@
     }
 
     /**
-     * @return whether this notification has a media session attached
-     * @hide
-     */
-    public boolean hasMediaSession() {
-        return extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) != null;
-    }
-
-    /**
      * @return the style class of this notification
      * @hide
      */
@@ -6861,18 +6853,20 @@
     }
 
     /**
-     * @return true if this is a media notification
+     * @return true if this is a media style notification with a media session
      *
      * @hide
      */
     public boolean isMediaNotification() {
         Class<? extends Style> style = getNotificationStyle();
-        if (MediaStyle.class.equals(style)) {
-            return true;
-        } else if (DecoratedMediaCustomViewStyle.class.equals(style)) {
-            return true;
-        }
-        return false;
+        boolean isMediaStyle = (MediaStyle.class.equals(style)
+                || DecoratedMediaCustomViewStyle.class.equals(style));
+
+        boolean hasMediaSession = (extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) != null
+                && extras.getParcelable(Notification.EXTRA_MEDIA_SESSION)
+                instanceof MediaSession.Token);
+
+        return isMediaStyle && hasMediaSession;
     }
 
     /**
diff --git a/core/java/android/app/OWNERS b/core/java/android/app/OWNERS
index 1da0a74..e099716 100644
--- a/core/java/android/app/OWNERS
+++ b/core/java/android/app/OWNERS
@@ -30,6 +30,8 @@
 per-file SystemServiceRegistry.java = file:/services/core/java/com/android/server/am/OWNERS
 per-file *UserSwitchObserver* = file:/services/core/java/com/android/server/am/OWNERS
 per-file UiAutomation.java = file:/services/accessibility/OWNERS
+per-file GameManager* = file:/GAME_MANAGER_OWNERS
+per-file IGameManager* = file:/GAME_MANAGER_OWNERS
 
 # ActivityThread
 per-file ActivityThread.java = file:/services/core/java/com/android/server/am/OWNERS
diff --git a/core/java/android/app/RemoteServiceException.java b/core/java/android/app/RemoteServiceException.java
index 4b32463..1038530 100644
--- a/core/java/android/app/RemoteServiceException.java
+++ b/core/java/android/app/RemoteServiceException.java
@@ -19,20 +19,109 @@
 import android.util.AndroidRuntimeException;
 
 /**
- * Exception used by {@link ActivityThread} to crash an app process.
+ * Exception used by {@link ActivityThread} to crash an app process for an unknown cause.
+ * An exception of this class is no longer supposed to be thrown. Instead, we use fine-grained
+ * sub-exceptions.
+ *
+ * Subclasses must be registered in
+ * {@link android.app.ActivityThread#throwRemoteServiceException(java.lang.String, int)}.
  *
  * @hide
  */
 public class RemoteServiceException extends AndroidRuntimeException {
-    /**
-     * The type ID passed to {@link IApplicationThread#scheduleCrash}.
-     *
-     * Assign a unique ID to each subclass. See the above method for the numbers that are already
-     * taken.
-     */
-    public static final int TYPE_ID = 0;
-
     public RemoteServiceException(String msg) {
         super(msg);
     }
+
+    /**
+     * Exception used to crash an app process when it didn't call {@link Service#startForeground}
+     * in time after the service was started with
+     * {@link android.content.Context#startForegroundService}.
+     *
+     * @hide
+     */
+    public static class ForegroundServiceDidNotStartInTimeException extends RemoteServiceException {
+        /** The type ID passed to {@link IApplicationThread#scheduleCrash}. */
+        public static final int TYPE_ID = 1;
+
+        public ForegroundServiceDidNotStartInTimeException(String msg) {
+            super(msg);
+        }
+    }
+
+    /**
+     * Exception used to crash an app process when the system received a RemoteException
+     * while delivering a broadcast to an app process.
+     *
+     * @hide
+     */
+    public static class CannotDeliverBroadcastException extends RemoteServiceException {
+        /** The type ID passed to {@link IApplicationThread#scheduleCrash}. */
+        public static final int TYPE_ID = 2;
+
+        public CannotDeliverBroadcastException(String msg) {
+            super(msg);
+        }
+    }
+
+    /**
+     * Exception used to crash an app process when the system received a RemoteException
+     * while posting a notification of a foreground service.
+     *
+     * @hide
+     */
+    public static class CannotPostForegroundServiceNotificationException
+            extends RemoteServiceException {
+        /** The type ID passed to {@link IApplicationThread#scheduleCrash}. */
+        public static final int TYPE_ID = 3;
+
+        public CannotPostForegroundServiceNotificationException(String msg) {
+            super(msg);
+        }
+    }
+
+    /**
+     * Exception used to crash an app process when the system finds an error in a foreground service
+     * notification.
+     *
+     * @hide
+     */
+    public static class BadForegroundServiceNotificationException extends RemoteServiceException {
+        /** The type ID passed to {@link IApplicationThread#scheduleCrash}. */
+        public static final int TYPE_ID = 4;
+
+        public BadForegroundServiceNotificationException(String msg) {
+            super(msg);
+        }
+    }
+
+    /**
+     * Exception used to crash an app process when it calls a setting activity that requires
+     * the {@code REQUEST_PASSWORD_COMPLEXITY} permission.
+     *
+     * @hide
+     */
+    public static class MissingRequestPasswordComplexityPermissionException
+            extends RemoteServiceException {
+        /** The type ID passed to {@link IApplicationThread#scheduleCrash}. */
+        public static final int TYPE_ID = 5;
+
+        public MissingRequestPasswordComplexityPermissionException(String msg) {
+            super(msg);
+        }
+    }
+
+    /**
+     * Exception used to crash an app process by {@code adb shell am crash}.
+     *
+     * @hide
+     */
+    public static class CrashedByAdbException extends RemoteServiceException {
+        /** The type ID passed to {@link IApplicationThread#scheduleCrash}. */
+        public static final int TYPE_ID = 6;
+
+        public CrashedByAdbException(String msg) {
+            super(msg);
+        }
+    }
 }
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index fc40179..089c269 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -196,14 +196,18 @@
 import android.permission.PermissionManager;
 import android.print.IPrintManager;
 import android.print.PrintManager;
+import android.safetycenter.SafetyCenterFrameworkInitializer;
 import android.scheduling.SchedulingFrameworkInitializer;
 import android.security.FileIntegrityManager;
 import android.security.IFileIntegrityService;
+import android.security.attestationverification.AttestationVerificationManager;
+import android.security.attestationverification.IAttestationVerificationManagerService;
 import android.service.oemlock.IOemLockService;
 import android.service.oemlock.OemLockManager;
 import android.service.persistentdata.IPersistentDataBlockService;
 import android.service.persistentdata.PersistentDataBlockManager;
 import android.service.vr.IVrManager;
+import android.supplementalprocess.SupplementalProcessFrameworkInitializer;
 import android.telecom.TelecomManager;
 import android.telephony.MmsManager;
 import android.telephony.TelephonyFrameworkInitializer;
@@ -1423,6 +1427,19 @@
                         return new FileIntegrityManager(ctx.getOuterContext(),
                                 IFileIntegrityService.Stub.asInterface(b));
                     }});
+
+        registerService(Context.ATTESTATION_VERIFICATION_SERVICE,
+                AttestationVerificationManager.class,
+                new CachedServiceFetcher<AttestationVerificationManager>() {
+                    @Override
+                    public AttestationVerificationManager createService(ContextImpl ctx)
+                            throws ServiceNotFoundException {
+                        IBinder b = ServiceManager.getServiceOrThrow(
+                                Context.ATTESTATION_VERIFICATION_SERVICE);
+                        return new AttestationVerificationManager(ctx.getOuterContext(),
+                                IAttestationVerificationManagerService.Stub.asInterface(b));
+                    }});
+
         //CHECKSTYLE:ON IndentationCheck
         registerService(Context.APP_INTEGRITY_SERVICE, AppIntegrityManager.class,
                 new CachedServiceFetcher<AppIntegrityManager>() {
@@ -1527,7 +1544,9 @@
             MediaFrameworkInitializer.registerServiceWrappers();
             RoleFrameworkInitializer.registerServiceWrappers();
             SchedulingFrameworkInitializer.registerServiceWrappers();
+            SupplementalProcessFrameworkInitializer.registerServiceWrappers();
             UwbFrameworkInitializer.registerServiceWrappers();
+            SafetyCenterFrameworkInitializer.registerServiceWrappers();
         } finally {
             // If any of the above code throws, we're in a pretty bad shape and the process
             // will likely crash, but we'll reset it just in case there's an exception handler...
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 828b171..58ded71 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -638,7 +638,7 @@
         final IAccessibilityServiceConnection connection;
         synchronized (mLock) {
             throwIfNotConnectedLocked();
-            AccessibilityInteractionClient.getInstance().clearCache();
+            AccessibilityInteractionClient.getInstance().clearCache(mConnectionId);
             connection = AccessibilityInteractionClient.getInstance()
                     .getConnection(mConnectionId);
         }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index d2963fb..5cfe09e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -684,8 +684,9 @@
      * A String extra holding the time zone {@link android.app.AlarmManager} that the device
      * will be set to.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
-     * provisioning via an NFC bump.
+     * <p>Use only for device owner provisioning. This extra can be returned by the admin app when
+     * performing the admin-integrated provisioning flow as a result of the {@link
+     * #ACTION_GET_PROVISIONING_MODE} activity.
      */
     public static final String EXTRA_PROVISIONING_TIME_ZONE
         = "android.app.extra.PROVISIONING_TIME_ZONE";
@@ -694,8 +695,9 @@
      * A Long extra holding the wall clock time (in milliseconds) to be set on the device's
      * {@link android.app.AlarmManager}.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
-     * provisioning via an NFC bump.
+     * <p>Use only for device owner provisioning. This extra can be returned by the admin app when
+     * performing the admin-integrated provisioning flow as a result of the {@link
+     * #ACTION_GET_PROVISIONING_MODE} activity.
      */
     public static final String EXTRA_PROVISIONING_LOCAL_TIME
         = "android.app.extra.PROVISIONING_LOCAL_TIME";
@@ -704,8 +706,9 @@
      * A String extra holding the {@link java.util.Locale} that the device will be set to.
      * Format: xx_yy, where xx is the language code, and yy the country code.
      *
-     * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
-     * provisioning via an NFC bump.
+     * <p>Use only for device owner provisioning. This extra can be returned by the admin app when
+     * performing the admin-integrated provisioning flow as a result of the {@link
+     * #ACTION_GET_PROVISIONING_MODE} activity.
      */
     public static final String EXTRA_PROVISIONING_LOCALE
         = "android.app.extra.PROVISIONING_LOCALE";
@@ -1001,7 +1004,10 @@
      * The default for this extra is {@code false} - by default, the admin of a fully-managed
      * device has the ability to grant sensors-related permissions.
      *
-     * <p>Use only for device owner provisioning.
+     * <p>Use only for device owner provisioning. This extra can be returned by the
+     * admin app when performing the admin-integrated provisioning flow as a result of the
+     * {@link #ACTION_GET_PROVISIONING_MODE} activity.
+     *
      * @see #ACTION_GET_PROVISIONING_MODE
      */
     public static final String EXTRA_PROVISIONING_SENSORS_PERMISSION_GRANT_OPT_OUT =
@@ -1070,6 +1076,9 @@
      *
      * <p>From {@link android.os.Build.VERSION_CODES#N} onwards, this is also supported for an
      * intent with action {@link #ACTION_PROVISION_MANAGED_PROFILE}.
+     *
+     * <p>This extra can also be returned by the admin app when performing the admin-integrated
+     * provisioning flow as a result of the {@link #ACTION_GET_PROVISIONING_MODE} activity.
      */
     public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION =
              "android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
@@ -1109,8 +1118,9 @@
      *
      * <p> Maximum 3 key-value pairs can be specified. The rest will be ignored.
      *
-     * <p> Use in an intent with action {@link #ACTION_PROVISION_MANAGED_PROFILE} or
-     * {@link #ACTION_PROVISION_MANAGED_DEVICE}
+     * <p> Can be used in an intent with action {@link #ACTION_PROVISION_MANAGED_PROFILE}. This
+     * extra can also be returned by the admin app when performing the admin-integrated
+     * provisioning flow as a result of the {@link #ACTION_GET_PROVISIONING_MODE} activity.
      */
     public static final String EXTRA_PROVISIONING_DISCLAIMERS =
             "android.app.extra.PROVISIONING_DISCLAIMERS";
@@ -3461,7 +3471,10 @@
      * Setting custom, overly-complicated password requirements leads to passwords that are hard
      * for users to remember and may not provide any security benefits given as Android uses
      * hardware-backed throttling to thwart online and offline brute-forcing of the device's
-     * screen lock.
+     * screen lock. Company-owned devices (fully-managed and organization-owned managed profile
+     * devices) are able to continue using this method, though it is recommended that
+     * {@link #setRequiredPasswordComplexity(int)} should be used instead.
+     *
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param quality The new desired quality. One of {@link #PASSWORD_QUALITY_UNSPECIFIED},
      *            {@link #PASSWORD_QUALITY_BIOMETRIC_WEAK},
@@ -7857,7 +7870,7 @@
     @SystemApi
     @RequiresPermission(anyOf = {
             android.Manifest.permission.MANAGE_USERS,
-            android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS,
+            android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
     })
     public ComponentName getDeviceOwnerComponentOnAnyUser() {
         return getDeviceOwnerComponentInner(/* callingUserOnly =*/ false);
@@ -7970,8 +7983,8 @@
      * Called by the system to find out whether the device is managed by a Device Owner.
      *
      * @return whether the device is managed by a Device Owner.
-     * @throws SecurityException if the caller is not the device owner, does not hold the
-     *         MANAGE_USERS permission and is not the system.
+     * @throws SecurityException if the caller is not the device owner, does not hold
+     *         MANAGE_USERS or MANAGE_PROFILE_AND_DEVICE_OWNERS permissions and is not the system.
      *
      * @hide
      */
@@ -7992,7 +8005,10 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+    })
     public String getDeviceOwnerNameOnAnyUser() {
         throwIfParentInstance("getDeviceOwnerNameOnAnyUser");
         if (mService != null) {
@@ -8382,7 +8398,10 @@
      * @throws IllegalArgumentException if the userId is invalid.
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+    })
     public @Nullable String getProfileOwnerNameAsUser(int userId) throws IllegalArgumentException {
         throwIfParentInstance("getProfileOwnerNameAsUser");
         if (mService != null) {
@@ -9263,7 +9282,7 @@
         throwIfParentInstance("getPermittedInputMethodsForCurrentUser");
         if (mService != null) {
             try {
-                return mService.getPermittedInputMethodsForCurrentUser();
+                return mService.getPermittedInputMethodsAsUser(UserHandle.myUserId());
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -9272,6 +9291,34 @@
     }
 
     /**
+     * Returns the list of input methods permitted.
+     *
+     * <p>When this method returns empty list means all input methods are allowed, if a non-empty
+     * list is returned it will contain the intersection of the permitted lists for any device or
+     * profile owners that apply to this user. It will also include any system input methods.
+     *
+     * @return List of input method package names.
+     * @hide
+     */
+    @UserHandleAware
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+            android.Manifest.permission.MANAGE_USERS
+            }, conditional = true)
+    public @NonNull List<String> getPermittedInputMethods() {
+        throwIfParentInstance("getPermittedInputMethods");
+        List<String> result = null;
+        if (mService != null) {
+            try {
+                result = mService.getPermittedInputMethodsAsUser(myUserId());
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return result != null ? result : Collections.emptyList();
+    }
+
+    /**
      * Called by a profile owner of a managed profile to set the packages that are allowed to use
      * a {@link android.service.notification.NotificationListenerService} in the primary user to
      * see notifications from the managed profile. By default all packages are permitted by this
@@ -11920,7 +11967,10 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+    })
     @UserProvisioningState
     public int getUserProvisioningState() {
         throwIfParentInstance("getUserProvisioningState");
@@ -13429,7 +13479,10 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+    })
     public boolean isManagedKiosk() {
         throwIfParentInstance("isManagedKiosk");
         if (mService != null) {
@@ -13458,7 +13511,10 @@
      * @hide
      */
     @SystemApi
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS
+    })
     public boolean isUnattendedManagedKiosk() {
         throwIfParentInstance("isUnattendedManagedKiosk");
         if (mService != null) {
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index cf48594..b9fcdf5 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -243,7 +243,7 @@
 
     boolean setPermittedInputMethods(in ComponentName admin,in List<String> packageList, boolean parent);
     List<String> getPermittedInputMethods(in ComponentName admin, boolean parent);
-    List<String> getPermittedInputMethodsForCurrentUser();
+    List<String> getPermittedInputMethodsAsUser(int userId);
     boolean isInputMethodPermittedByAdmin(in ComponentName admin, String packageName, int userId, boolean parent);
 
     boolean setPermittedCrossProfileNotificationListeners(in ComponentName admin, in List<String> packageList);
diff --git a/core/java/android/app/communal/CommunalManager.java b/core/java/android/app/communal/CommunalManager.java
index 375a9af..4602d6b 100644
--- a/core/java/android/app/communal/CommunalManager.java
+++ b/core/java/android/app/communal/CommunalManager.java
@@ -19,6 +19,9 @@
 import android.Manifest;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.Disabled;
+import android.compat.annotation.Overridable;
 import android.content.Context;
 import android.os.RemoteException;
 
@@ -32,6 +35,27 @@
 public final class CommunalManager {
     private final ICommunalManager mService;
 
+    /**
+     * This change id is used to annotate packages which can run in communal mode by default,
+     * without requiring user opt-in.
+     *
+     * @hide
+     */
+    @ChangeId
+    @Overridable
+    @Disabled
+    public static final long ALLOW_COMMUNAL_MODE_BY_DEFAULT = 203673428L;
+
+    /**
+     * This change id is used to annotate packages which are allowed to run in communal mode.
+     *
+     * @hide
+     */
+    @ChangeId
+    @Overridable
+    @Disabled
+    public static final long ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT = 200324021L;
+
     public CommunalManager(ICommunalManager service) {
         mService = service;
     }
diff --git a/core/java/android/app/communal/OWNERS b/core/java/android/app/communal/OWNERS
new file mode 100644
index 0000000..b02883d
--- /dev/null
+++ b/core/java/android/app/communal/OWNERS
@@ -0,0 +1,4 @@
+brycelee@google.com
+justinkoh@google.com
+lusilva@google.com
+xilei@google.com
\ No newline at end of file
diff --git a/core/java/android/app/timezonedetector/TimeZoneDetector.java b/core/java/android/app/timezonedetector/TimeZoneDetector.java
index a71cffe..ceab02f 100644
--- a/core/java/android/app/timezonedetector/TimeZoneDetector.java
+++ b/core/java/android/app/timezonedetector/TimeZoneDetector.java
@@ -96,6 +96,13 @@
     String SHELL_COMMAND_SUGGEST_TELEPHONY_TIME_ZONE = "suggest_telephony_time_zone";
 
     /**
+     * A shell command that enables telephony time zone fallback. See {@link
+     * com.android.server.timezonedetector.TimeZoneDetectorStrategy} for details.
+     * @hide
+     */
+    String SHELL_COMMAND_ENABLE_TELEPHONY_FALLBACK = "enable_telephony_fallback";
+
+    /**
      * A shared utility method to create a {@link ManualTimeZoneSuggestion}.
      *
      * @hide
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index cf00cbd..20122fb 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -51,7 +51,6 @@
 import android.content.Attributable;
 import android.content.AttributionSource;
 import android.content.Context;
-import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Build;
 import android.os.IBinder;
@@ -59,7 +58,6 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
-import android.os.SynchronousResultReceiver;
 import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Pair;
@@ -69,6 +67,7 @@
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.time.Duration;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -82,7 +81,6 @@
 import java.util.UUID;
 import java.util.WeakHashMap;
 import java.util.concurrent.Executor;
-import java.util.concurrent.TimeoutException;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 /**
@@ -402,6 +400,16 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface ScanMode {}
 
+    /** @hide */
+    @IntDef(value = {
+            BluetoothStatusCodes.SUCCESS,
+            BluetoothStatusCodes.ERROR_UNKNOWN,
+            BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED,
+            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface ScanModeStatusCode {}
+
     /**
      * Indicates that both inquiry scan and page scan are disabled on the local
      * Bluetooth adapter. Therefore this device is neither discoverable
@@ -1618,7 +1626,7 @@
                 return mService.getScanMode(mAttributionSource);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "", e);
+            throw e.rethrowFromSystemServer();
         } finally {
             mServiceLock.readLock().unlock();
         }
@@ -1626,143 +1634,110 @@
     }
 
     /**
-     * Set the Bluetooth scan mode of the local Bluetooth adapter.
-     * <p>The Bluetooth scan mode determines if the local adapter is
-     * connectable and/or discoverable from remote Bluetooth devices.
-     * <p>For privacy reasons, discoverable mode is automatically turned off
-     * after <code>durationMillis</code> milliseconds. For example, 120000 milliseconds should be
-     * enough for a remote device to initiate and complete its discovery process.
-     * <p>Valid scan mode values are:
-     * {@link #SCAN_MODE_NONE},
-     * {@link #SCAN_MODE_CONNECTABLE},
-     * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
-     * <p>If Bluetooth state is not {@link #STATE_ON}, this API
-     * will return false. After turning on Bluetooth,
-     * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
-     * to get the updated value.
+     * Set the local Bluetooth adapter connectablility and discoverability.
+     * <p>If the scan mode is set to {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE},
+     * it will change to {@link #SCAN_MODE_CONNECTABLE} after the discoverable timeout.
+     * The discoverable timeout can be set with {@link #setDiscoverableTimeout} and
+     * checked with {@link #getDiscoverableTimeout}. By default, the timeout is usually
+     * 120 seconds on phones which is enough for a remote device to initiate and complete
+     * its discovery process.
      * <p>Applications cannot set the scan mode. They should use
-     * <code>startActivityForResult(
-     * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
-     * </code>instead.
+     * {@link #ACTION_REQUEST_DISCOVERABLE} instead.
      *
-     * @param mode valid scan mode
-     * @param durationMillis time in milliseconds to apply scan mode, only used for {@link
-     * #SCAN_MODE_CONNECTABLE_DISCOVERABLE}
-     * @return true if the scan mode was set, false otherwise
+     * @param mode represents the desired state of the local device scan mode
+     *
+     * @return status code indicating whether the scan mode was successfully set
      * @hide
      */
-    @UnsupportedAppUsage(publicAlternatives = "Use {@link #ACTION_REQUEST_DISCOVERABLE}, which "
-            + "shows UI that confirms the user wants to go into discoverable mode.")
-    @RequiresLegacyBluetoothPermission
+    @SystemApi
     @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public boolean setScanMode(@ScanMode int mode, long durationMillis) {
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.BLUETOOTH_SCAN,
+            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+    })
+    @ScanModeStatusCode
+    public int setScanMode(@ScanMode int mode) {
         if (getState() != STATE_ON) {
-            return false;
+            return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
         }
         try {
             mServiceLock.readLock().lock();
             if (mService != null) {
-                int durationSeconds = Math.toIntExact(durationMillis / 1000);
-                return mService.setScanMode(mode, durationSeconds, mAttributionSource);
+                return mService.setScanMode(mode, mAttributionSource);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } catch (ArithmeticException ex) {
-            Log.e(TAG, "setScanMode: Duration in seconds outside of the bounds of an int");
-            throw new IllegalArgumentException("Duration not in bounds. In seconds, the "
-                    + "durationMillis must be in the range of an int");
+            throw e.rethrowFromSystemServer();
         } finally {
             mServiceLock.readLock().unlock();
         }
-        return false;
+        return BluetoothStatusCodes.ERROR_UNKNOWN;
     }
 
     /**
-     * Set the Bluetooth scan mode of the local Bluetooth adapter.
-     * <p>The Bluetooth scan mode determines if the local adapter is
-     * connectable and/or discoverable from remote Bluetooth devices.
-     * <p>For privacy reasons, discoverable mode is automatically turned off
-     * after <code>duration</code> seconds. For example, 120 seconds should be
-     * enough for a remote device to initiate and complete its discovery
-     * process.
-     * <p>Valid scan mode values are:
-     * {@link #SCAN_MODE_NONE},
-     * {@link #SCAN_MODE_CONNECTABLE},
-     * {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
-     * <p>If Bluetooth state is not {@link #STATE_ON}, this API
-     * will return false. After turning on Bluetooth,
-     * wait for {@link #ACTION_STATE_CHANGED} with {@link #STATE_ON}
-     * to get the updated value.
-     * <p>Applications cannot set the scan mode. They should use
-     * <code>startActivityForResult(
-     * BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE})
-     * </code>instead.
+     * Get the timeout duration of the {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE}.
      *
-     * @param mode valid scan mode
-     * @return true if the scan mode was set, false otherwise
+     * @return the duration of the discoverable timeout or null if an error has occurred
+     */
+    @RequiresBluetoothScanPermission
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
+    public @Nullable Duration getDiscoverableTimeout() {
+        if (getState() != STATE_ON) {
+            return null;
+        }
+        try {
+            mServiceLock.readLock().lock();
+            if (mService != null) {
+                long timeout = mService.getDiscoverableTimeout(mAttributionSource);
+                return (timeout == -1) ? null : Duration.ofSeconds(timeout);
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } finally {
+            mServiceLock.readLock().unlock();
+        }
+        return null;
+    }
+
+    /**
+     * Set the total time the Bluetooth local adapter will stay discoverable when
+     * {@link #setScanMode} is called with {@link #SCAN_MODE_CONNECTABLE_DISCOVERABLE} mode.
+     * After this timeout, the scan mode will fallback to {@link #SCAN_MODE_CONNECTABLE}.
+     * <p>If <code>timeout</code> is set to 0, no timeout will occur and the scan mode will
+     * be persisted until a subsequent call to {@link #setScanMode}.
+     *
+     * @param timeout represents the total duration the local Bluetooth adapter will remain
+     *                discoverable, or no timeout if set to 0
+     * @return whether the timeout was successfully set
+     * @throws IllegalArgumentException if <code>timeout</code> duration in seconds is more
+     *         than {@link Integer#MAX_VALUE}
      * @hide
      */
-    @UnsupportedAppUsage
-    @RequiresLegacyBluetoothPermission
+    @SystemApi
     @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public boolean setScanMode(@ScanMode int mode) {
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.BLUETOOTH_SCAN,
+            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
+    })
+    @ScanModeStatusCode
+    public int setDiscoverableTimeout(@NonNull Duration timeout) {
         if (getState() != STATE_ON) {
-            return false;
+            return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED;
+        }
+        if (timeout.toSeconds() > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException("Timeout in seconds must be less or equal to "
+                    + Integer.MAX_VALUE);
         }
         try {
             mServiceLock.readLock().lock();
             if (mService != null) {
-                return mService.setScanMode(mode, getDiscoverableTimeout(), mAttributionSource);
+                return mService.setDiscoverableTimeout(timeout.toSeconds(), mAttributionSource);
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "", e);
+            throw e.rethrowFromSystemServer();
         } finally {
             mServiceLock.readLock().unlock();
         }
-        return false;
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public int getDiscoverableTimeout() {
-        if (getState() != STATE_ON) {
-            return -1;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                return mService.getDiscoverableTimeout(mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
-        return -1;
-    }
-
-    /** @hide */
-    @UnsupportedAppUsage
-    @RequiresBluetoothScanPermission
-    @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)
-    public void setDiscoverableTimeout(int timeout) {
-        if (getState() != STATE_ON) {
-            return;
-        }
-        try {
-            mServiceLock.readLock().lock();
-            if (mService != null) {
-                mService.setDiscoverableTimeout(timeout, mAttributionSource);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
-        } finally {
-            mServiceLock.readLock().unlock();
-        }
+        return BluetoothStatusCodes.ERROR_UNKNOWN;
     }
 
     /**
@@ -2424,38 +2399,6 @@
     }
 
     /**
-     * Return the record of {@link BluetoothActivityEnergyInfo} object that
-     * has the activity and energy info. This can be used to ascertain what
-     * the controller has been up to, since the last sample.
-     *
-     * @param updateType Type of info, cached vs refreshed.
-     * @return a record with {@link BluetoothActivityEnergyInfo} or null if report is unavailable or
-     * unsupported
-     * @hide
-     * @deprecated use the asynchronous {@link #requestControllerActivityEnergyInfo(ResultReceiver)}
-     * instead.
-     */
-    @Deprecated
-    @RequiresBluetoothConnectPermission
-    @RequiresPermission(allOf = {
-            android.Manifest.permission.BLUETOOTH_CONNECT,
-            android.Manifest.permission.BLUETOOTH_PRIVILEGED,
-    })
-    public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
-        SynchronousResultReceiver receiver = new SynchronousResultReceiver();
-        requestControllerActivityEnergyInfo(receiver);
-        try {
-            SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
-            if (result.bundle != null) {
-                return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
-            }
-        } catch (TimeoutException e) {
-            Log.e(TAG, "getControllerActivityEnergyInfo timed out");
-        }
-        return null;
-    }
-
-    /**
      * Request the record of {@link BluetoothActivityEnergyInfo} object that
      * has the activity and energy info. This can be used to ascertain what
      * the controller has been up to, since the last sample.
diff --git a/core/java/android/bluetooth/BluetoothClass.java b/core/java/android/bluetooth/BluetoothClass.java
index 7fe18a0..69525b5 100755
--- a/core/java/android/bluetooth/BluetoothClass.java
+++ b/core/java/android/bluetooth/BluetoothClass.java
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Build;
@@ -327,21 +328,26 @@
         return Arrays.copyOfRange(bytes, 1, bytes.length);
     }
 
-    /** @hide */
-    @UnsupportedAppUsage
     public static final int PROFILE_HEADSET = 0;
-    /** @hide */
-    @UnsupportedAppUsage
+
     public static final int PROFILE_A2DP = 1;
+
     /** @hide */
+    @SystemApi
     public static final int PROFILE_OPP = 2;
-    /** @hide */
+
     public static final int PROFILE_HID = 3;
+
     /** @hide */
+    @SystemApi
     public static final int PROFILE_PANU = 4;
+
     /** @hide */
+    @SystemApi
     public static final int PROFILE_NAP = 5;
+
     /** @hide */
+    @SystemApi
     public static final int PROFILE_A2DP_SINK = 6;
 
     /**
@@ -350,11 +356,9 @@
      * given class bits might support specified profile. It is not accurate for all
      * devices. It tries to err on the side of false positives.
      *
-     * @param profile The profile to be checked
-     * @return True if this device might support specified profile.
-     * @hide
+     * @param profile the profile to be checked
+     * @return whether this device supports specified profile
      */
-    @UnsupportedAppUsage
     public boolean doesClassMatch(int profile) {
         if (profile == PROFILE_A2DP) {
             if (hasService(Service.RENDER)) {
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 3e799de..08e0178 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -16,6 +16,8 @@
 
 package android.bluetooth;
 
+import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.RequiresNoPermission;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressLint;
@@ -26,6 +28,8 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
@@ -709,33 +713,85 @@
      * notification
      * @return true, if the notification has been triggered successfully
      * @throws IllegalArgumentException
+     *
+     * @deprecated Use {@link BluetoothGattServer#notifyCharacteristicChanged(BluetoothDevice,
+     * BluetoothGattCharacteristic, boolean, byte[])}  as this is not memory safe.
      */
+    @Deprecated
     @RequiresLegacyBluetoothPermission
     @RequiresBluetoothConnectPermission
     @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
     public boolean notifyCharacteristicChanged(BluetoothDevice device,
             BluetoothGattCharacteristic characteristic, boolean confirm) {
+        return notifyCharacteristicChanged(device, characteristic, confirm,
+                characteristic.getValue()) == BluetoothStatusCodes.SUCCESS;
+    }
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(value = {
+            BluetoothStatusCodes.SUCCESS,
+            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION,
+            BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_PRIVILEGED_PERMISSION,
+            BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED,
+            BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND,
+            BluetoothStatusCodes.ERROR_GATT_WRITE_NOT_ALLOWED,
+            BluetoothStatusCodes.ERROR_GATT_WRITE_REQUEST_BUSY,
+            BluetoothStatusCodes.ERROR_UNKNOWN
+    })
+    public @interface NotifyCharacteristicReturnValues{}
+
+    /**
+     * Send a notification or indication that a local characteristic has been
+     * updated.
+     *
+     * <p>A notification or indication is sent to the remote device to signal
+     * that the characteristic has been updated. This function should be invoked
+     * for every client that requests notifications/indications by writing
+     * to the "Client Configuration" descriptor for the given characteristic.
+     *
+     * @param device the remote device to receive the notification/indication
+     * @param characteristic the local characteristic that has been updated
+     * @param confirm {@code true} to request confirmation from the client (indication) or
+     * {@code false} to send a notification
+     * @param value the characteristic value
+     * @return whether the notification has been triggered successfully
+     * @throws IllegalArgumentException if the characteristic value or service is null
+     */
+    @RequiresLegacyBluetoothPermission
+    @RequiresBluetoothConnectPermission
+    @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+    @NotifyCharacteristicReturnValues
+    public int notifyCharacteristicChanged(@NonNull BluetoothDevice device,
+            @NonNull BluetoothGattCharacteristic characteristic, boolean confirm,
+            @NonNull byte[] value) {
         if (VDBG) Log.d(TAG, "notifyCharacteristicChanged() - device: " + device.getAddress());
-        if (mService == null || mServerIf == 0) return false;
+        if (mService == null || mServerIf == 0) {
+            return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND;
+        }
 
+        if (characteristic == null) {
+            throw new IllegalArgumentException("characteristic must not be null");
+        }
+        if (device == null) {
+            throw new IllegalArgumentException("device must not be null");
+        }
         BluetoothGattService service = characteristic.getService();
-        if (service == null) return false;
-
-        if (characteristic.getValue() == null) {
-            throw new IllegalArgumentException("Chracteristic value is empty. Use "
-                    + "BluetoothGattCharacteristic#setvalue to update");
+        if (service == null) {
+            throw new IllegalArgumentException("Characteristic must have a non-null service");
+        }
+        if (value == null) {
+            throw new IllegalArgumentException("Characteristic value must not be null");
         }
 
         try {
-            mService.sendNotification(mServerIf, device.getAddress(),
+            return mService.sendNotification(mServerIf, device.getAddress(),
                     characteristic.getInstanceId(), confirm,
-                    characteristic.getValue(), mAttributionSource);
+                    value, mAttributionSource);
         } catch (RemoteException e) {
             Log.e(TAG, "", e);
-            return false;
+            throw e.rethrowFromSystemServer();
         }
-
-        return true;
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 1655b62..db5b751 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -18,7 +18,6 @@
 
 import android.annotation.RequiresNoPermission;
 import android.annotation.RequiresPermission;
-import android.annotation.SuppressLint;
 import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.net.LocalSocket;
@@ -266,7 +265,7 @@
             throw new IOException("bt socket acept failed");
         }
 
-        as.mPfd = new ParcelFileDescriptor(fds[0]);
+        as.mPfd = ParcelFileDescriptor.dup(fds[0]);
         as.mSocket = LocalSocket.createConnectedLocalSocket(fds[0]);
         as.mSocketIS = as.mSocket.getInputStream();
         as.mSocketOS = as.mSocket.getOutputStream();
diff --git a/core/java/android/bluetooth/BluetoothStatusCodes.java b/core/java/android/bluetooth/BluetoothStatusCodes.java
index ca01784..5ba7bb1 100644
--- a/core/java/android/bluetooth/BluetoothStatusCodes.java
+++ b/core/java/android/bluetooth/BluetoothStatusCodes.java
@@ -40,7 +40,7 @@
 
     /**
      * Error code indicating that the API call was initiated by neither the system nor the active
-     * Zuser
+     * user
      */
     public static final int ERROR_BLUETOOTH_NOT_ALLOWED = 2;
 
diff --git a/core/java/android/bluetooth/le/AdvertiseData.java b/core/java/android/bluetooth/le/AdvertiseData.java
index cec6580..fdf62ec 100644
--- a/core/java/android/bluetooth/le/AdvertiseData.java
+++ b/core/java/android/bluetooth/le/AdvertiseData.java
@@ -25,6 +25,7 @@
 import android.util.SparseArray;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -47,6 +48,9 @@
     @NonNull
     private final List<ParcelUuid> mServiceSolicitationUuids;
 
+    @Nullable
+    private final List<TransportDiscoveryData> mTransportDiscoveryData;
+
     private final SparseArray<byte[]> mManufacturerSpecificData;
     private final Map<ParcelUuid, byte[]> mServiceData;
     private final boolean mIncludeTxPowerLevel;
@@ -54,12 +58,14 @@
 
     private AdvertiseData(List<ParcelUuid> serviceUuids,
             List<ParcelUuid> serviceSolicitationUuids,
+            List<TransportDiscoveryData> transportDiscoveryData,
             SparseArray<byte[]> manufacturerData,
             Map<ParcelUuid, byte[]> serviceData,
             boolean includeTxPowerLevel,
             boolean includeDeviceName) {
         mServiceUuids = serviceUuids;
         mServiceSolicitationUuids = serviceSolicitationUuids;
+        mTransportDiscoveryData = transportDiscoveryData;
         mManufacturerSpecificData = manufacturerData;
         mServiceData = serviceData;
         mIncludeTxPowerLevel = includeTxPowerLevel;
@@ -83,6 +89,17 @@
     }
 
     /**
+     * Returns a list of {@link TransportDiscoveryData} within the advertisement.
+     */
+    @NonNull
+    public List<TransportDiscoveryData> getTransportDiscoveryData() {
+        if (mTransportDiscoveryData == null) {
+            return Collections.emptyList();
+        }
+        return mTransportDiscoveryData;
+    }
+
+    /**
      * Returns an array of manufacturer Id and the corresponding manufacturer specific data. The
      * manufacturer id is a non-negative number assigned by Bluetooth SIG.
      */
@@ -116,8 +133,8 @@
      */
     @Override
     public int hashCode() {
-        return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mManufacturerSpecificData,
-                mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel);
+        return Objects.hash(mServiceUuids, mServiceSolicitationUuids, mTransportDiscoveryData,
+                mManufacturerSpecificData, mServiceData, mIncludeDeviceName, mIncludeTxPowerLevel);
     }
 
     /**
@@ -134,6 +151,7 @@
         AdvertiseData other = (AdvertiseData) obj;
         return Objects.equals(mServiceUuids, other.mServiceUuids)
                 && Objects.equals(mServiceSolicitationUuids, other.mServiceSolicitationUuids)
+                && Objects.equals(mTransportDiscoveryData, other.mTransportDiscoveryData)
                 && BluetoothLeUtils.equals(mManufacturerSpecificData,
                     other.mManufacturerSpecificData)
                 && BluetoothLeUtils.equals(mServiceData, other.mServiceData)
@@ -144,7 +162,8 @@
     @Override
     public String toString() {
         return "AdvertiseData [mServiceUuids=" + mServiceUuids + ", mServiceSolicitationUuids="
-                + mServiceSolicitationUuids + ", mManufacturerSpecificData="
+                + mServiceSolicitationUuids + ", mTransportDiscoveryData="
+                + mTransportDiscoveryData + ", mManufacturerSpecificData="
                 + BluetoothLeUtils.toString(mManufacturerSpecificData) + ", mServiceData="
                 + BluetoothLeUtils.toString(mServiceData)
                 + ", mIncludeTxPowerLevel=" + mIncludeTxPowerLevel + ", mIncludeDeviceName="
@@ -162,6 +181,8 @@
         dest.writeTypedArray(mServiceSolicitationUuids.toArray(
                 new ParcelUuid[mServiceSolicitationUuids.size()]), flags);
 
+        dest.writeTypedList(mTransportDiscoveryData);
+
         // mManufacturerSpecificData could not be null.
         dest.writeInt(mManufacturerSpecificData.size());
         for (int i = 0; i < mManufacturerSpecificData.size(); ++i) {
@@ -197,6 +218,12 @@
                         builder.addServiceSolicitationUuid(uuid);
                     }
 
+                    List<TransportDiscoveryData> transportDiscoveryData =
+                            in.createTypedArrayList(TransportDiscoveryData.CREATOR);
+                    for (TransportDiscoveryData tdd : transportDiscoveryData) {
+                        builder.addTransportDiscoveryData(tdd);
+                    }
+
                     int manufacturerSize = in.readInt();
                     for (int i = 0; i < manufacturerSize; ++i) {
                         int manufacturerId = in.readInt();
@@ -223,6 +250,9 @@
         private List<ParcelUuid> mServiceUuids = new ArrayList<ParcelUuid>();
         @NonNull
         private List<ParcelUuid> mServiceSolicitationUuids = new ArrayList<ParcelUuid>();
+        @Nullable
+        private List<TransportDiscoveryData> mTransportDiscoveryData =
+                new ArrayList<TransportDiscoveryData>();
         private SparseArray<byte[]> mManufacturerSpecificData = new SparseArray<byte[]>();
         private Map<ParcelUuid, byte[]> mServiceData = new ArrayMap<ParcelUuid, byte[]>();
         private boolean mIncludeTxPowerLevel;
@@ -256,6 +286,7 @@
             mServiceSolicitationUuids.add(serviceSolicitationUuid);
             return this;
         }
+
         /**
          * Add service data to advertise data.
          *
@@ -274,6 +305,23 @@
         }
 
         /**
+         * Add Transport Discovery Data to advertise data.
+         *
+         * @param transportDiscoveryData Transport Discovery Data, consisting of one or more
+         * Transport Blocks. Transport Discovery Data AD Type Code is already included.
+         * @throws IllegalArgumentException If the {@code transportDiscoveryData} is empty
+         */
+        @NonNull
+        public Builder addTransportDiscoveryData(
+                @NonNull TransportDiscoveryData transportDiscoveryData) {
+            if (transportDiscoveryData == null) {
+                throw new IllegalArgumentException("transportDiscoveryData is null");
+            }
+            mTransportDiscoveryData.add(transportDiscoveryData);
+            return this;
+        }
+
+        /**
          * Add manufacturer specific data.
          * <p>
          * Please refer to the Bluetooth Assigned Numbers document provided by the <a
@@ -319,8 +367,8 @@
          */
         public AdvertiseData build() {
             return new AdvertiseData(mServiceUuids, mServiceSolicitationUuids,
-                    mManufacturerSpecificData, mServiceData, mIncludeTxPowerLevel,
-                    mIncludeDeviceName);
+                    mTransportDiscoveryData, mManufacturerSpecificData, mServiceData,
+                    mIncludeTxPowerLevel, mIncludeDeviceName);
         }
     }
 }
diff --git a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
index 5802974..b9f8a57 100644
--- a/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
+++ b/core/java/android/bluetooth/le/BluetoothLeAdvertiser.java
@@ -567,6 +567,9 @@
                         + num128BitUuids * BluetoothUuid.UUID_BYTES_128_BIT;
             }
         }
+        for (TransportDiscoveryData transportDiscoveryData : data.getTransportDiscoveryData()) {
+            size += OVERHEAD_BYTES_PER_FIELD + transportDiscoveryData.totalBytes();
+        }
         for (ParcelUuid uuid : data.getServiceData().keySet()) {
             int uuidLen = BluetoothUuid.uuidToBytes(uuid).length;
             size += OVERHEAD_BYTES_PER_FIELD + uuidLen
diff --git a/core/java/android/bluetooth/le/TransportBlock.java b/core/java/android/bluetooth/le/TransportBlock.java
new file mode 100644
index 0000000..b388bed
--- /dev/null
+++ b/core/java/android/bluetooth/le/TransportBlock.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2014 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 android.bluetooth.le;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+
+/**
+ * Wrapper for Transport Discovery Data Transport Blocks.
+ * This class represents a Transport Block from a Transport Discovery Data.
+ *
+ * @see TransportDiscoveryData
+ * @see AdvertiseData
+ */
+public final class TransportBlock implements Parcelable {
+    private static final String TAG = "TransportBlock";
+    private final int mOrgId;
+    private final int mTdsFlags;
+    private final int mTransportDataLength;
+    private final byte[] mTransportData;
+
+    /**
+     * Creates an instance of TransportBlock from raw data.
+     *
+     * @param orgId the Organization ID
+     * @param tdsFlags the TDS flags
+     * @param transportDataLength the total length of the Transport Data
+     * @param transportData the Transport Data
+     */
+    public TransportBlock(int orgId, int tdsFlags, int transportDataLength,
+            @Nullable byte[] transportData) {
+        mOrgId = orgId;
+        mTdsFlags = tdsFlags;
+        mTransportDataLength = transportDataLength;
+        mTransportData = transportData;
+    }
+
+    private TransportBlock(Parcel in) {
+        mOrgId = in.readInt();
+        mTdsFlags = in.readInt();
+        mTransportDataLength = in.readInt();
+        mTransportData = new byte[mTransportDataLength];
+        in.readByteArray(mTransportData);
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mOrgId);
+        dest.writeInt(mTdsFlags);
+        dest.writeInt(mTransportDataLength);
+        dest.writeByteArray(mTransportData);
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public static final @NonNull Creator<TransportBlock> CREATOR = new Creator<TransportBlock>() {
+        @Override
+        public TransportBlock createFromParcel(Parcel in) {
+            return new TransportBlock(in);
+        }
+
+        @Override
+        public TransportBlock[] newArray(int size) {
+            return new TransportBlock[size];
+        }
+    };
+
+    /**
+     * Gets the Organization ID of the Transport Block which corresponds to one of the
+     * the Bluetooth SIG Assigned Numbers.
+     */
+    public int getOrgId() {
+        return mOrgId;
+    }
+
+    /**
+     * Gets the TDS flags of the Transport Block which represents the role of the device and
+     * information about its state and supported features.
+     */
+    public int getTdsFlags() {
+        return mTdsFlags;
+    }
+
+    /**
+     * Gets the total number of octets in the Transport Data field in this Transport Block.
+     */
+    public int getTransportDataLength() {
+        return mTransportDataLength;
+    }
+
+    /**
+     * Gets the Transport Data of the Transport Block which contains organization-specific data.
+     */
+    @Nullable
+    public byte[] getTransportData() {
+        return mTransportData;
+    }
+
+    /**
+     * Converts this TransportBlock to byte array
+     *
+     * @return byte array representation of this Transport Block or null if the conversion failed
+     */
+    @Nullable
+    public byte[] toByteArray() {
+        try {
+            ByteBuffer buffer = ByteBuffer.allocate(totalBytes());
+            buffer.put((byte) mOrgId);
+            buffer.put((byte) mTdsFlags);
+            buffer.put((byte) mTransportDataLength);
+            if (mTransportData != null) {
+                buffer.put(mTransportData);
+            }
+            return buffer.array();
+        } catch (BufferOverflowException e) {
+            Log.e(TAG, "Error converting to byte array: " + e.toString());
+            return null;
+        }
+    }
+
+    /**
+     * @return total byte count of this TransportBlock
+     */
+    public int totalBytes() {
+        // 3 uint8 + byte[] length
+        int size = 3 + mTransportDataLength;
+        return size;
+    }
+}
diff --git a/core/java/android/bluetooth/le/TransportDiscoveryData.java b/core/java/android/bluetooth/le/TransportDiscoveryData.java
new file mode 100644
index 0000000..c8e97f9
--- /dev/null
+++ b/core/java/android/bluetooth/le/TransportDiscoveryData.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2014 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 android.bluetooth.le;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import java.nio.BufferOverflowException;
+import java.nio.BufferUnderflowException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Wrapper for Transport Discovery Data AD Type.
+ * This class contains the Transport Discovery Data AD Type Code as well as
+ * a list of potential Transport Blocks.
+ *
+ * @see AdvertiseData
+ */
+public final class TransportDiscoveryData implements Parcelable {
+    private static final String TAG = "TransportDiscoveryData";
+    private final int mTransportDataType;
+    private final List<TransportBlock> mTransportBlocks;
+
+    /**
+     * Creates a TransportDiscoveryData instance.
+     *
+     * @param transportDataType the Transport Discovery Data AD Type
+     * @param transportBlocks the list of Transport Blocks
+     */
+    public TransportDiscoveryData(int transportDataType,
+            @NonNull List<TransportBlock> transportBlocks) {
+        mTransportDataType = transportDataType;
+        mTransportBlocks = transportBlocks;
+    }
+
+    /**
+     * Creates a TransportDiscoveryData instance from byte arrays.
+     *
+     * Uses the transport discovery data bytes and parses them into an usable class.
+     *
+     * @param transportDiscoveryData the raw discovery data
+     */
+    public TransportDiscoveryData(@NonNull byte[] transportDiscoveryData) {
+        ByteBuffer byteBuffer = ByteBuffer.wrap(transportDiscoveryData);
+        mTransportBlocks = new ArrayList();
+        if (byteBuffer.remaining() > 0) {
+            mTransportDataType = byteBuffer.get();
+        } else {
+            mTransportDataType = -1;
+        }
+        try {
+            while (byteBuffer.remaining() > 0) {
+                int orgId = byteBuffer.get();
+                int tdsFlags = byteBuffer.get();
+                int transportDataLength = byteBuffer.get();
+                byte[] transportData = new byte[transportDataLength];
+                byteBuffer.get(transportData, 0, transportDataLength);
+                mTransportBlocks.add(new TransportBlock(orgId, tdsFlags,
+                        transportDataLength, transportData));
+            }
+        } catch (BufferUnderflowException e) {
+            Log.e(TAG, "Error while parsing data: " + e.toString());
+        }
+    }
+
+    private TransportDiscoveryData(Parcel in) {
+        mTransportDataType = in.readInt();
+        mTransportBlocks = in.createTypedArrayList(TransportBlock.CREATOR);
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(mTransportDataType);
+        dest.writeTypedList(mTransportBlocks);
+    }
+
+    public static final @NonNull Creator<TransportDiscoveryData> CREATOR =
+            new Creator<TransportDiscoveryData>() {
+                @Override
+                public TransportDiscoveryData createFromParcel(Parcel in) {
+                    return new TransportDiscoveryData(in);
+                }
+
+                @Override
+                public TransportDiscoveryData[] newArray(int size) {
+                    return new TransportDiscoveryData[size];
+                }
+    };
+
+    /**
+     * Gets the transport data type.
+     */
+    public int getTransportDataType() {
+        return mTransportDataType;
+    }
+
+    /**
+     * @return the list of {@link TransportBlock} in this TransportDiscoveryData
+     *         or an empty list if there are no Transport Blocks
+     */
+    @NonNull
+    public List<TransportBlock> getTransportBlocks() {
+        if (mTransportBlocks == null) {
+            return Collections.emptyList();
+        }
+        return mTransportBlocks;
+    }
+
+    /**
+     * Converts this TransportDiscoveryData to byte array
+     *
+     * @return byte array representation of this Transport Discovery Data or null if the
+     *         conversion failed
+     */
+    @Nullable
+    public byte[] toByteArray() {
+        try {
+            ByteBuffer buffer = ByteBuffer.allocate(totalBytes());
+            buffer.put((byte) mTransportDataType);
+            for (TransportBlock transportBlock : getTransportBlocks()) {
+                buffer.put(transportBlock.toByteArray());
+            }
+            return buffer.array();
+        } catch (BufferOverflowException e) {
+            Log.e(TAG, "Error converting to byte array: " + e.toString());
+            return null;
+        }
+    }
+
+    /**
+     * @return total byte count of this TransportDataDiscovery
+     */
+    public int totalBytes() {
+        int size = 1; // Counting Transport Data Type here.
+        for (TransportBlock transportBlock : getTransportBlocks()) {
+            size += transportBlock.totalBytes();
+        }
+        return size;
+    }
+}
diff --git a/core/java/android/companion/AssociationInfo.java b/core/java/android/companion/AssociationInfo.java
index ab1eb1f..3f02aa2 100644
--- a/core/java/android/companion/AssociationInfo.java
+++ b/core/java/android/companion/AssociationInfo.java
@@ -15,29 +15,24 @@
  */
 package android.companion;
 
-import static android.companion.DeviceId.TYPE_MAC_ADDRESS;
-
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.annotation.UserIdInt;
+import android.net.MacAddress;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
 import java.util.Objects;
-import java.util.Set;
 
 /**
- * A record indicating that a device with a given address was confirmed by the user to be
- * associated to a given companion app
- *
- * @hide
- * TODO(b/1979395): un-hide and rename to AssociationInfo when implementing public APIs that use
- *                  this class.
+ * Details for a specific "association" that has been established between an app and companion
+ * device.
+ * <p>
+ * An association gives an app the ability to interact with a companion device without needing to
+ * acquire broader runtime permissions. An association only exists after the user has confirmed that
+ * an app should have access to a companion device.
  */
 public final class AssociationInfo implements Parcelable {
     /**
@@ -45,15 +40,16 @@
      * Disclosed to the clients (ie. companion applications) for referring to this record (eg. in
      * {@code disassociate()} API call).
      */
-    private final int mAssociationId;
+    private final int mId;
 
     private final @UserIdInt int mUserId;
     private final @NonNull String mPackageName;
 
-    private final @NonNull List<DeviceId> mDeviceIds;
+    private final @Nullable MacAddress mDeviceMacAddress;
+    private final @Nullable CharSequence mDisplayName;
     private final @Nullable String mDeviceProfile;
 
-    private final boolean mManagedByCompanionApp;
+    private final boolean mSelfManaged;
     private boolean mNotifyOnDeviceNearby;
     private final long mTimeApprovedMs;
 
@@ -63,23 +59,28 @@
      *
      * @hide
      */
-    public AssociationInfo(int associationId, @UserIdInt int userId, @NonNull String packageName,
-            @NonNull List<DeviceId> deviceIds, @Nullable String deviceProfile,
-            boolean managedByCompanionApp, boolean notifyOnDeviceNearby, long timeApprovedMs) {
-        if (associationId <= 0) {
+    public AssociationInfo(int id, @UserIdInt int userId, @NonNull String packageName,
+            @Nullable MacAddress macAddress, @Nullable CharSequence displayName,
+            @Nullable String deviceProfile, boolean selfManaged, boolean notifyOnDeviceNearby,
+            long timeApprovedMs) {
+        if (id <= 0) {
             throw new IllegalArgumentException("Association ID should be greater than 0");
         }
-        validateDeviceIds(deviceIds);
+        if (macAddress == null && displayName == null) {
+            throw new IllegalArgumentException("MAC address and the Display Name must NOT be null "
+                    + "at the same time");
+        }
 
-        mAssociationId = associationId;
+        mId = id;
 
         mUserId = userId;
         mPackageName = packageName;
 
+        mDeviceMacAddress = macAddress;
+        mDisplayName = displayName;
         mDeviceProfile = deviceProfile;
-        mDeviceIds = new ArrayList<>(deviceIds);
 
-        mManagedByCompanionApp = managedByCompanionApp;
+        mSelfManaged = selfManaged;
         mNotifyOnDeviceNearby = notifyOnDeviceNearby;
         mTimeApprovedMs = timeApprovedMs;
     }
@@ -87,55 +88,66 @@
     /**
      * @return the unique ID of this association record.
      */
-    public int getAssociationId() {
-        return mAssociationId;
+    public int getId() {
+        return mId;
     }
 
-    /** @hide */
-    public int getUserId() {
+    /**
+     * @return the ID of the user who "owns" this association.
+     * @hide
+     */
+    public @UserIdInt int getUserId() {
         return mUserId;
     }
 
-    /** @hide */
+    /**
+     * @return the package name of the app which this association refers to.
+     * @hide
+     */
+    @SystemApi
     public @NonNull String getPackageName() {
         return mPackageName;
     }
 
     /**
-     * @return list of the device's IDs. At any time a device has at least 1 ID.
+     * @return the MAC address of the device.
      */
-    public @NonNull List<DeviceId> getDeviceIds() {
-        return Collections.unmodifiableList(mDeviceIds);
-    }
-
-    /**
-     * @param type type of the ID.
-     * @return ID of the type if the device has such ID, {@code null} otherwise.
-     */
-    public @Nullable String getIdOfType(@NonNull String type) {
-        for (int i = mDeviceIds.size() - 1; i >= 0; i--) {
-            final DeviceId id = mDeviceIds.get(i);
-            if (Objects.equals(mDeviceIds.get(i).getType(), type)) return id.getValue();
-        }
-        return null;
+    public @Nullable MacAddress getDeviceMacAddress() {
+        return mDeviceMacAddress;
     }
 
     /** @hide */
-    public @NonNull String getDeviceMacAddress() {
-        return Objects.requireNonNull(getIdOfType(TYPE_MAC_ADDRESS),
-                "MAC address of this device is not specified.");
+    public @Nullable String getDeviceMacAddressAsString() {
+        return mDeviceMacAddress != null ? mDeviceMacAddress.toString().toUpperCase() : null;
     }
 
     /**
-     * @return the profile of the device.
+     * @return the display name of the companion device (optionally) provided by the companion
+     * application.
+     *
+     * @see AssociationRequest.Builder#setDisplayName(CharSequence)
+     */
+    public @Nullable CharSequence getDisplayName() {
+        return mDisplayName;
+    }
+
+    /**
+     * @return the companion device profile used when establishing this
+     *         association, or {@code null} if no specific profile was used.
+     * @see AssociationRequest.Builder#setDeviceProfile(String)
      */
     public @Nullable String getDeviceProfile() {
         return mDeviceProfile;
     }
 
-    /** @hide */
-    public boolean isManagedByCompanionApp() {
-        return mManagedByCompanionApp;
+    /**
+     * @return whether the association is managed by the companion application it belongs to.
+     * @see AssociationRequest.Builder#setSelfManaged(boolean)
+     * @hide
+     */
+    @SystemApi
+    public boolean isSelfManaged() {
+        return mSelfManaged;
     }
 
     /**
@@ -161,15 +173,40 @@
         return mUserId == userId && Objects.equals(mPackageName, packageName);
     }
 
+    /**
+     * Utility method for checking if the association represents a device with the given MAC
+     * address.
+     *
+     * @return {@code false} if the association is "self-managed".
+     *         {@code false} if the {@code addr} is {@code null} or is not a valid MAC address.
+     *         Otherwise - the result of {@link MacAddress#equals(Object)}
+     *
+     * @hide
+     */
+    public boolean isLinkedTo(@Nullable String addr) {
+        if (mSelfManaged) return false;
+
+        if (addr == null) return false;
+
+        final MacAddress macAddress;
+        try {
+            macAddress = MacAddress.fromString(addr);
+        } catch (IllegalArgumentException e) {
+            return false;
+        }
+        return macAddress.equals(mDeviceMacAddress);
+    }
+
     @Override
     public String toString() {
         return "Association{"
-                + "mAssociationId=" + mAssociationId
+                + "mId=" + mId
                 + ", mUserId=" + mUserId
                 + ", mPackageName='" + mPackageName + '\''
-                + ", mDeviceIds=" + mDeviceIds
+                + ", mDeviceMacAddress=" + mDeviceMacAddress
+                + ", mDisplayName='" + mDisplayName + '\''
                 + ", mDeviceProfile='" + mDeviceProfile + '\''
-                + ", mManagedByCompanionApp=" + mManagedByCompanionApp
+                + ", mSelfManaged=" + mSelfManaged
                 + ", mNotifyOnDeviceNearby=" + mNotifyOnDeviceNearby
                 + ", mTimeApprovedMs=" + new Date(mTimeApprovedMs)
                 + '}';
@@ -180,20 +217,21 @@
         if (this == o) return true;
         if (!(o instanceof AssociationInfo)) return false;
         final AssociationInfo that = (AssociationInfo) o;
-        return mAssociationId == that.mAssociationId
+        return mId == that.mId
                 && mUserId == that.mUserId
-                && mManagedByCompanionApp == that.mManagedByCompanionApp
+                && mSelfManaged == that.mSelfManaged
                 && mNotifyOnDeviceNearby == that.mNotifyOnDeviceNearby
                 && mTimeApprovedMs == that.mTimeApprovedMs
                 && Objects.equals(mPackageName, that.mPackageName)
-                && Objects.equals(mDeviceProfile, that.mDeviceProfile)
-                && Objects.equals(mDeviceIds, that.mDeviceIds);
+                && Objects.equals(mDeviceMacAddress, that.mDeviceMacAddress)
+                && Objects.equals(mDisplayName, that.mDisplayName)
+                && Objects.equals(mDeviceProfile, that.mDeviceProfile);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mAssociationId, mUserId, mPackageName, mDeviceIds, mDeviceProfile,
-                mManagedByCompanionApp, mNotifyOnDeviceNearby, mTimeApprovedMs);
+        return Objects.hash(mId, mUserId, mPackageName, mDeviceMacAddress, mDisplayName,
+                mDeviceProfile, mSelfManaged, mNotifyOnDeviceNearby, mTimeApprovedMs);
     }
 
     @Override
@@ -203,33 +241,36 @@
 
     @Override
     public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mAssociationId);
+        dest.writeInt(mId);
 
         dest.writeInt(mUserId);
         dest.writeString(mPackageName);
 
-        dest.writeParcelableList(mDeviceIds, 0);
+        dest.writeTypedObject(mDeviceMacAddress, 0);
+        dest.writeCharSequence(mDisplayName);
         dest.writeString(mDeviceProfile);
 
-        dest.writeBoolean(mManagedByCompanionApp);
+        dest.writeBoolean(mSelfManaged);
         dest.writeBoolean(mNotifyOnDeviceNearby);
         dest.writeLong(mTimeApprovedMs);
     }
 
     private AssociationInfo(@NonNull Parcel in) {
-        mAssociationId = in.readInt();
+        mId = in.readInt();
 
         mUserId = in.readInt();
         mPackageName = in.readString();
 
-        mDeviceIds = in.readParcelableList(new ArrayList<>(), DeviceId.class.getClassLoader());
+        mDeviceMacAddress = in.readTypedObject(MacAddress.CREATOR);
+        mDisplayName = in.readCharSequence();
         mDeviceProfile = in.readString();
 
-        mManagedByCompanionApp = in.readBoolean();
+        mSelfManaged = in.readBoolean();
         mNotifyOnDeviceNearby = in.readBoolean();
         mTimeApprovedMs = in.readLong();
     }
 
+    @NonNull
     public static final Parcelable.Creator<AssociationInfo> CREATOR =
             new Parcelable.Creator<AssociationInfo>() {
         @Override
@@ -242,19 +283,4 @@
             return new AssociationInfo(in);
         }
     };
-
-    private static void validateDeviceIds(@NonNull List<DeviceId> ids) {
-        if (ids.isEmpty()) throw new IllegalArgumentException("Device must have at least 1 id.");
-
-        // Make sure none of the IDs are null, and they all have different types.
-        final Set<String> types = new HashSet<>(ids.size());
-        for (int i = ids.size() - 1; i >= 0; i--) {
-            final DeviceId deviceId = ids.get(i);
-            if (deviceId == null) throw new IllegalArgumentException("DeviceId must not be null");
-            if (!types.add(deviceId.getType())) {
-                throw new IllegalArgumentException(
-                        "DeviceId cannot have multiple IDs of the same type");
-            }
-        }
-    }
 }
diff --git a/core/java/android/companion/AssociationRequest.java b/core/java/android/companion/AssociationRequest.java
index 7d1aabc..1dc161c 100644
--- a/core/java/android/companion/AssociationRequest.java
+++ b/core/java/android/companion/AssociationRequest.java
@@ -16,6 +16,8 @@
 
 package android.companion;
 
+import static android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED;
+
 import static com.android.internal.util.CollectionUtils.emptyIfNull;
 
 import android.Manifest;
@@ -58,9 +60,6 @@
         genBuilder = false,
         genConstDefs = false)
 public final class AssociationRequest implements Parcelable {
-
-    private static final String LOG_TAG = AssociationRequest.class.getSimpleName();
-
     /**
      * Device profile: watch.
      *
@@ -116,7 +115,7 @@
     /**
      * Whether only a single device should match the provided filter.
      *
-     * When scanning for a single device with a specifc {@link BluetoothDeviceFilter} mac
+     * When scanning for a single device with a specific {@link BluetoothDeviceFilter} mac
      * address, bonded devices are also searched among. This allows to obtain the necessary app
      * privileges even if the device is already paired.
      */
@@ -134,6 +133,24 @@
     private @Nullable @DeviceProfile String mDeviceProfile = null;
 
     /**
+     * The Display name of the device to be shown in the CDM confirmation UI. Must be non-null for
+     * "self-managed" association.
+     */
+    private final @Nullable CharSequence mDisplayName;
+
+    /**
+     * Whether the association is to be managed by the companion application.
+     */
+    private final boolean mSelfManaged;
+
+    /**
+     * Indicates that the application would prefer the CompanionDeviceManager to collect an explicit
+     * confirmation from the user before creating an association, even if such confirmation is not
+     * required.
+     */
+    private final boolean mForceConfirmation;
+
+    /**
      * The app package making the request.
      *
      * Populated by the system.
@@ -167,8 +184,30 @@
      */
     private boolean mSkipPrompt = false;
 
-    private void onConstructed() {
-        mCreationTime = System.currentTimeMillis();
+    /**
+     * Whether the association is to be managed by the companion application.
+     *
+     * @see Builder#setSelfManaged(boolean)
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(REQUEST_COMPANION_SELF_MANAGED)
+    public boolean isSelfManaged() {
+        return mSelfManaged;
+    }
+
+    /**
+     * Indicates that the application would prefer the CompanionDeviceManager to collect an explicit
+     * confirmation from the user before creating an association, even if such confirmation is not
+     * required.
+     *
+     * @see Builder#setForceConfirmation(boolean)
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(REQUEST_COMPANION_SELF_MANAGED)
+    public boolean isForceConfirmation() {
+        return mForceConfirmation;
     }
 
     /** @hide */
@@ -199,20 +238,27 @@
         return mDeviceFilters;
     }
 
+    private void onConstructed() {
+        mCreationTime = System.currentTimeMillis();
+    }
+
     /**
      * A builder for {@link AssociationRequest}
      */
     public static final class Builder extends OneTimeUseBuilder<AssociationRequest> {
         private boolean mSingleDevice = false;
-        @Nullable private ArrayList<DeviceFilter<?>> mDeviceFilters = null;
-        private @Nullable String mDeviceProfile = null;
+        private @Nullable ArrayList<DeviceFilter<?>> mDeviceFilters = null;
+        private @Nullable String mDeviceProfile;
+        private @Nullable CharSequence mDisplayName;
+        private boolean mSelfManaged = false;
+        private boolean mForceConfirmation = false;
 
         public Builder() {}
 
         /**
          * Whether only a single device should match the provided filter.
          *
-         * When scanning for a single device with a specifc {@link BluetoothDeviceFilter} mac
+         * When scanning for a single device with a specific {@link BluetoothDeviceFilter} mac
          * address, bonded devices are also searched among. This allows to obtain the necessary app
          * privileges even if the device is already paired.
          *
@@ -249,14 +295,65 @@
             return this;
         }
 
+        /**
+         * Adds a display name.
+         * Generally {@link AssociationRequest}s are not required to provide a display name, except
+         * for request for creating "self-managed" associations, which MUST provide a display name.
+         *
+         * @param displayName the display name of the device.
+         */
+        @NonNull
+        public Builder setDisplayName(@NonNull CharSequence displayName) {
+            checkNotUsed();
+            mDisplayName = Objects.requireNonNull(displayName);
+            return this;
+        }
+
+        /**
+         * Indicate whether the association would be managed by the companion application.
+         *
+         * Requests for creating "self-managed" association MUST provide a Display name.
+         *
+         * @see #setDisplayName(CharSequence)
+         * @hide
+         */
+        @SystemApi
+        @RequiresPermission(REQUEST_COMPANION_SELF_MANAGED)
+        @NonNull
+        public Builder setSelfManaged(boolean selfManaged) {
+            checkNotUsed();
+            mSelfManaged = selfManaged;
+            return this;
+        }
+
+        /**
+         * Indicates whether the application would prefer the CompanionDeviceManager to collect an
+         * explicit confirmation from the user before creating an association, even if such
+         * confirmation is not required.
+         *
+         * @hide
+         */
+        @SystemApi
+        @RequiresPermission(REQUEST_COMPANION_SELF_MANAGED)
+        @NonNull
+        public Builder setForceConfirmation(boolean forceConfirmation) {
+            checkNotUsed();
+            mForceConfirmation = forceConfirmation;
+            return this;
+        }
+
         /** @inheritDoc */
         @NonNull
         @Override
         public AssociationRequest build() {
             markUsed();
-            return new AssociationRequest(
-                    mSingleDevice, emptyIfNull(mDeviceFilters),
-                    mDeviceProfile, null, null, -1L, false);
+            if (mSelfManaged && mDisplayName == null) {
+                throw new IllegalStateException("Request for a self-managed association MUST "
+                        + "provide the display name of the device");
+            }
+            return new AssociationRequest(mSingleDevice, emptyIfNull(mDeviceFilters),
+                    mDeviceProfile, mDisplayName, mSelfManaged, mForceConfirmation,
+                    null, null, -1L, false);
         }
     }
 
@@ -283,13 +380,22 @@
      * @param singleDevice
      *   Whether only a single device should match the provided filter.
      *
-     *   When scanning for a single device with a specifc {@link BluetoothDeviceFilter} mac
+     *   When scanning for a single device with a specific {@link BluetoothDeviceFilter} mac
      *   address, bonded devices are also searched among. This allows to obtain the necessary app
      *   privileges even if the device is already paired.
      * @param deviceFilters
      *   If set, only devices matching either of the given filters will be shown to the user
      * @param deviceProfile
      *   If set, association will be requested as a corresponding kind of device
+     * @param displayName
+     *   The Display name of the device to be shown in the CDM confirmation UI. Must be non-null for
+     *   "self-managed" association.
+     * @param selfManaged
+     *   Whether the association is to be managed by the companion application.
+     * @param forceConfirmation
+     *   Indicates that the application would prefer the CompanionDeviceManager to collect an explicit
+     *   confirmation from the user before creating an association, even if such confirmation is not
+     *   required.
      * @param callingPackage
      *   The app package making the request.
      *
@@ -311,6 +417,9 @@
             boolean singleDevice,
             @NonNull List<DeviceFilter<?>> deviceFilters,
             @Nullable @DeviceProfile String deviceProfile,
+            @Nullable CharSequence displayName,
+            boolean selfManaged,
+            boolean forceConfirmation,
             @Nullable String callingPackage,
             @Nullable String deviceProfilePrivilegesDescription,
             long creationTime,
@@ -322,6 +431,9 @@
         this.mDeviceProfile = deviceProfile;
         com.android.internal.util.AnnotationValidations.validate(
                 DeviceProfile.class, null, mDeviceProfile);
+        this.mDisplayName = displayName;
+        this.mSelfManaged = selfManaged;
+        this.mForceConfirmation = forceConfirmation;
         this.mCallingPackage = callingPackage;
         this.mDeviceProfilePrivilegesDescription = deviceProfilePrivilegesDescription;
         this.mCreationTime = creationTime;
@@ -341,6 +453,17 @@
     }
 
     /**
+     * The Display name of the device to be shown in the CDM confirmation UI. Must be non-null for
+     * "self-managed" association.
+     *
+     * @hide
+     */
+    @DataClass.Generated.Member
+    public @Nullable CharSequence getDisplayName() {
+        return mDisplayName;
+    }
+
+    /**
      * The app package making the request.
      *
      * Populated by the system.
@@ -396,6 +519,9 @@
                 "singleDevice = " + mSingleDevice + ", " +
                 "deviceFilters = " + mDeviceFilters + ", " +
                 "deviceProfile = " + mDeviceProfile + ", " +
+                "displayName = " + mDisplayName + ", " +
+                "selfManaged = " + mSelfManaged + ", " +
+                "forceConfirmation = " + mForceConfirmation + ", " +
                 "callingPackage = " + mCallingPackage + ", " +
                 "deviceProfilePrivilegesDescription = " + mDeviceProfilePrivilegesDescription + ", " +
                 "creationTime = " + mCreationTime + ", " +
@@ -419,6 +545,9 @@
                 && mSingleDevice == that.mSingleDevice
                 && Objects.equals(mDeviceFilters, that.mDeviceFilters)
                 && Objects.equals(mDeviceProfile, that.mDeviceProfile)
+                && Objects.equals(mDisplayName, that.mDisplayName)
+                && mSelfManaged == that.mSelfManaged
+                && mForceConfirmation == that.mForceConfirmation
                 && Objects.equals(mCallingPackage, that.mCallingPackage)
                 && Objects.equals(mDeviceProfilePrivilegesDescription, that.mDeviceProfilePrivilegesDescription)
                 && mCreationTime == that.mCreationTime
@@ -435,6 +564,9 @@
         _hash = 31 * _hash + Boolean.hashCode(mSingleDevice);
         _hash = 31 * _hash + Objects.hashCode(mDeviceFilters);
         _hash = 31 * _hash + Objects.hashCode(mDeviceProfile);
+        _hash = 31 * _hash + Objects.hashCode(mDisplayName);
+        _hash = 31 * _hash + Boolean.hashCode(mSelfManaged);
+        _hash = 31 * _hash + Boolean.hashCode(mForceConfirmation);
         _hash = 31 * _hash + Objects.hashCode(mCallingPackage);
         _hash = 31 * _hash + Objects.hashCode(mDeviceProfilePrivilegesDescription);
         _hash = 31 * _hash + Long.hashCode(mCreationTime);
@@ -448,15 +580,19 @@
         // You can override field parcelling by defining methods like:
         // void parcelFieldName(Parcel dest, int flags) { ... }
 
-        byte flg = 0;
+        int flg = 0;
         if (mSingleDevice) flg |= 0x1;
-        if (mSkipPrompt) flg |= 0x40;
+        if (mSelfManaged) flg |= 0x10;
+        if (mForceConfirmation) flg |= 0x20;
+        if (mSkipPrompt) flg |= 0x200;
         if (mDeviceProfile != null) flg |= 0x4;
-        if (mCallingPackage != null) flg |= 0x8;
-        if (mDeviceProfilePrivilegesDescription != null) flg |= 0x10;
-        dest.writeByte(flg);
+        if (mDisplayName != null) flg |= 0x8;
+        if (mCallingPackage != null) flg |= 0x40;
+        if (mDeviceProfilePrivilegesDescription != null) flg |= 0x80;
+        dest.writeInt(flg);
         dest.writeParcelableList(mDeviceFilters, flags);
         if (mDeviceProfile != null) dest.writeString(mDeviceProfile);
+        if (mDisplayName != null) dest.writeCharSequence(mDisplayName);
         if (mCallingPackage != null) dest.writeString(mCallingPackage);
         if (mDeviceProfilePrivilegesDescription != null) dest.writeString(mDeviceProfilePrivilegesDescription);
         dest.writeLong(mCreationTime);
@@ -473,14 +609,17 @@
         // You can override field unparcelling by defining methods like:
         // static FieldType unparcelFieldName(Parcel in) { ... }
 
-        byte flg = in.readByte();
+        int flg = in.readInt();
         boolean singleDevice = (flg & 0x1) != 0;
-        boolean skipPrompt = (flg & 0x40) != 0;
+        boolean selfManaged = (flg & 0x10) != 0;
+        boolean forceConfirmation = (flg & 0x20) != 0;
+        boolean skipPrompt = (flg & 0x200) != 0;
         List<DeviceFilter<?>> deviceFilters = new ArrayList<>();
         in.readParcelableList(deviceFilters, DeviceFilter.class.getClassLoader());
         String deviceProfile = (flg & 0x4) == 0 ? null : in.readString();
-        String callingPackage = (flg & 0x8) == 0 ? null : in.readString();
-        String deviceProfilePrivilegesDescription = (flg & 0x10) == 0 ? null : in.readString();
+        CharSequence displayName = (flg & 0x8) == 0 ? null : (CharSequence) in.readCharSequence();
+        String callingPackage = (flg & 0x40) == 0 ? null : in.readString();
+        String deviceProfilePrivilegesDescription = (flg & 0x80) == 0 ? null : in.readString();
         long creationTime = in.readLong();
 
         this.mSingleDevice = singleDevice;
@@ -490,6 +629,9 @@
         this.mDeviceProfile = deviceProfile;
         com.android.internal.util.AnnotationValidations.validate(
                 DeviceProfile.class, null, mDeviceProfile);
+        this.mDisplayName = displayName;
+        this.mSelfManaged = selfManaged;
+        this.mForceConfirmation = forceConfirmation;
         this.mCallingPackage = callingPackage;
         this.mDeviceProfilePrivilegesDescription = deviceProfilePrivilegesDescription;
         this.mCreationTime = creationTime;
@@ -513,10 +655,10 @@
     };
 
     @DataClass.Generated(
-            time = 1635190605212L,
+            time = 1637228802427L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/core/java/android/companion/AssociationRequest.java",
-            inputSignatures = "private static final  java.lang.String LOG_TAG\npublic static final  java.lang.String DEVICE_PROFILE_WATCH\npublic static final @android.annotation.RequiresPermission @android.annotation.SystemApi java.lang.String DEVICE_PROFILE_APP_STREAMING\npublic static final @android.annotation.RequiresPermission @android.annotation.SystemApi java.lang.String DEVICE_PROFILE_AUTOMOTIVE_PROJECTION\nprivate  boolean mSingleDevice\nprivate @com.android.internal.util.DataClass.PluralOf(\"deviceFilter\") @android.annotation.NonNull java.util.List<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate @android.annotation.Nullable @android.companion.AssociationRequest.DeviceProfile java.lang.String mDeviceProfile\nprivate @android.annotation.Nullable java.lang.String mCallingPackage\nprivate @android.annotation.Nullable java.lang.String mDeviceProfilePrivilegesDescription\nprivate  long mCreationTime\nprivate  boolean mSkipPrompt\nprivate  void onConstructed()\npublic  void setCallingPackage(java.lang.String)\npublic  void setDeviceProfilePrivilegesDescription(java.lang.String)\npublic  void setSkipPrompt(boolean)\npublic @android.compat.annotation.UnsupportedAppUsage boolean isSingleDevice()\npublic @android.annotation.NonNull @android.compat.annotation.UnsupportedAppUsage java.util.List<android.companion.DeviceFilter<?>> getDeviceFilters()\nclass AssociationRequest extends java.lang.Object implements [android.os.Parcelable]\nprivate  boolean mSingleDevice\nprivate @android.annotation.Nullable java.util.ArrayList<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate @android.annotation.Nullable java.lang.String mDeviceProfile\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setSingleDevice(boolean)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setDeviceProfile(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override android.companion.AssociationRequest build()\nclass Builder extends android.provider.OneTimeUseBuilder<android.companion.AssociationRequest> implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true, genHiddenGetters=true, genParcelable=true, genHiddenConstructor=true, genBuilder=false, genConstDefs=false)")
+            inputSignatures = "public static final  java.lang.String DEVICE_PROFILE_WATCH\npublic static final @android.annotation.RequiresPermission @android.annotation.SystemApi java.lang.String DEVICE_PROFILE_APP_STREAMING\npublic static final @android.annotation.RequiresPermission @android.annotation.SystemApi java.lang.String DEVICE_PROFILE_AUTOMOTIVE_PROJECTION\nprivate  boolean mSingleDevice\nprivate @com.android.internal.util.DataClass.PluralOf(\"deviceFilter\") @android.annotation.NonNull java.util.List<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate @android.annotation.Nullable @android.companion.AssociationRequest.DeviceProfile java.lang.String mDeviceProfile\nprivate final @android.annotation.Nullable java.lang.CharSequence mDisplayName\nprivate final  boolean mSelfManaged\nprivate final  boolean mForceConfirmation\nprivate @android.annotation.Nullable java.lang.String mCallingPackage\nprivate @android.annotation.Nullable java.lang.String mDeviceProfilePrivilegesDescription\nprivate  long mCreationTime\nprivate  boolean mSkipPrompt\npublic @android.annotation.SystemApi @android.annotation.RequiresPermission boolean isSelfManaged()\npublic @android.annotation.SystemApi @android.annotation.RequiresPermission boolean isForceConfirmation()\npublic  void setCallingPackage(java.lang.String)\npublic  void setDeviceProfilePrivilegesDescription(java.lang.String)\npublic  void setSkipPrompt(boolean)\npublic @android.compat.annotation.UnsupportedAppUsage boolean isSingleDevice()\npublic @android.annotation.NonNull @android.compat.annotation.UnsupportedAppUsage java.util.List<android.companion.DeviceFilter<?>> getDeviceFilters()\nprivate  void onConstructed()\nclass AssociationRequest extends java.lang.Object implements [android.os.Parcelable]\nprivate  boolean mSingleDevice\nprivate @android.annotation.Nullable java.util.ArrayList<android.companion.DeviceFilter<?>> mDeviceFilters\nprivate @android.annotation.Nullable java.lang.String mDeviceProfile\nprivate @android.annotation.Nullable java.lang.CharSequence mDisplayName\nprivate  boolean mSelfManaged\nprivate  boolean mForceConfirmation\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setSingleDevice(boolean)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder addDeviceFilter(android.companion.DeviceFilter<?>)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setDeviceProfile(java.lang.String)\npublic @android.annotation.NonNull android.companion.AssociationRequest.Builder setDisplayName(java.lang.CharSequence)\npublic @android.annotation.SystemApi @android.annotation.RequiresPermission @android.annotation.NonNull android.companion.AssociationRequest.Builder setSelfManaged(boolean)\npublic @android.annotation.SystemApi @android.annotation.RequiresPermission @android.annotation.NonNull android.companion.AssociationRequest.Builder setForceConfirmation(boolean)\npublic @android.annotation.NonNull @java.lang.Override android.companion.AssociationRequest build()\nclass Builder extends android.provider.OneTimeUseBuilder<android.companion.AssociationRequest> implements []\n@com.android.internal.util.DataClass(genToString=true, genEqualsHashCode=true, genHiddenGetters=true, genParcelable=true, genHiddenConstructor=true, genBuilder=false, genConstDefs=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 6719a69..2b12f12 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -16,23 +16,26 @@
 
 package android.companion;
 
-import android.Manifest;
+import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING;
+import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION;
+import static android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
+import android.annotation.UserHandleAware;
 import android.app.Activity;
-import android.app.Application;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothDevice;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.PackageManager;
 import android.net.MacAddress;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -40,10 +43,16 @@
 import android.util.ExceptionUtils;
 import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.CollectionUtils;
+
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
-import java.util.function.BiConsumer;
+import java.util.concurrent.Executor;
+import java.util.function.Consumer;
 
 /**
  * System level service for managing companion devices
@@ -75,10 +84,21 @@
      *     <li>for Bluetooth LE - {@link android.bluetooth.le.ScanResult}</li>
      *     <li>for WiFi - {@link android.net.wifi.ScanResult}</li>
      * </ul>
+     *
+     * @deprecated use {@link #EXTRA_ASSOCIATION} instead.
      */
+    @Deprecated
     public static final String EXTRA_DEVICE = "android.companion.extra.DEVICE";
 
     /**
+     * Extra field name for the {@link AssociationInfo} object, included into
+     * {@link android.content.Intent} which application receive in
+     * {@link Activity#onActivityResult(int, int, Intent)} after the application's
+     * {@link AssociationRequest} was successfully processed and an association was created.
+     */
+    public static final String EXTRA_ASSOCIATION = "android.companion.extra.ASSOCIATION";
+
+    /**
      * The package name of the companion device discovery component.
      *
      * @hide
@@ -87,30 +107,121 @@
             "com.android.companiondevicemanager";
 
     /**
-     * A callback to receive once at least one suitable device is found, or the search failed
-     * (e.g. timed out)
+     * Callback for applications to receive updates about and the outcome of
+     * {@link AssociationRequest} issued via {@code associate()} call.
+     *
+     * <p>
+     * The {@link Callback#onAssociationPending(IntentSender)} is invoked after the
+     * {@link AssociationRequest} has been checked by the Companion Device Manager Service and is
+     * pending user's approval.
+     *
+     * The {@link IntentSender} received as an argument to
+     * {@link Callback#onAssociationPending(IntentSender)} "encapsulates" an {@link Activity}
+     * that has UI for the user to:
+     * <ul>
+     * <li>
+     * choose the device to associate the application with (if multiple eligible devices are
+     * available)
+     * </li>
+     * <li>confirm the association</li>
+     * <li>
+     * approve the privileges the application will be granted if the association is to be created
+     * </li>
+     * </ul>
+     *
+     * If the Companion Device Manager Service needs to scan for the devices, the {@link Activity}
+     * will also display the status and the progress of the scan.
+     *
+     * Note that Companion Device Manager Service will only start the scanning after the
+     * {@link Activity} was launched and became visible.
+     *
+     * Applications are expected to launch the UI using the received {@link IntentSender} via
+     * {@link Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int)}.
+     * </p>
+     *
+     * <p>
+     * Upon receiving user's confirmation Companion Device Manager Service will create an
+     * association and will send an {@link AssociationInfo} object that represents the created
+     * association back to the application both via
+     * {@link Callback#onAssociationCreated(AssociationInfo)} and
+     * via {@link Activity#setResult(int, Intent)}.
+     * In the latter the {@code resultCode} will be set to {@link Activity#RESULT_OK} and the
+     * {@code data} {@link Intent} will contain {@link AssociationInfo} extra named
+     * {@link #EXTRA_ASSOCIATION}.
+     * <pre>
+     * <code>
+     *   if (resultCode == Activity.RESULT_OK) {
+     *     AssociationInfo associationInfo = data.getParcelableExtra(EXTRA_ASSOCIATION);
+     *   }
+     * </code>
+     * </pre>
+     * </p>
+     *
+     * <p>
+     *  If the Companion Device Manager Service is not able to create an association, it will
+     *  invoke {@link Callback#onFailure(CharSequence)}.
+     *
+     *  If this happened after the application has launched the UI (eg. the user chose to reject
+     *  the association), the outcome will also be delivered to the applications via
+     *  {@link Activity#setResult(int)} with the {@link Activity#RESULT_CANCELED}
+     *  {@code resultCode}.
+     * </p>
+     *
+     * <p>
+     * Note that in some cases the Companion Device Manager Service may not need to collect
+     * user's approval for creating an association. In such cases, this method will not be
+     * invoked, and {@link #onAssociationCreated(AssociationInfo)} may be invoked right away.
+     * </p>
+     *
+     * @see #associate(AssociationRequest, Executor, Callback)
+     * @see #associate(AssociationRequest, Callback, Handler)
+     * @see #EXTRA_ASSOCIATION
      */
     public abstract static class Callback {
+        /**
+         * @deprecated method was renamed to onAssociationPending() to provide better clarity; both
+         * methods are functionally equivalent and only one needs to be overridden.
+         *
+         * @see #onAssociationPending(IntentSender)
+         */
+        @Deprecated
+        public void onDeviceFound(@NonNull IntentSender intentSender) {}
 
         /**
-         * Called once at least one suitable device is found
+         * Invoked when the association needs to approved by the user.
          *
-         * @param chooserLauncher a {@link IntentSender} to launch the UI for user to select a
-         *                        device
+         * Applications should launch the {@link Activity} "encapsulated" in {@code intentSender}
+         * {@link IntentSender} object by calling
+         * {@link Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int)}.
+         *
+         * @param intentSender an {@link IntentSender} which applications should use to launch
+         *                     the UI for the user to confirm the association.
          */
-        public abstract void onDeviceFound(IntentSender chooserLauncher);
+        public void onAssociationPending(@NonNull IntentSender intentSender) {
+            onDeviceFound(intentSender);
+        }
 
         /**
-         * Called if there was an error looking for device(s)
+         * Invoked when the association is created.
          *
-         * @param error the cause of the error
+         * @param associationInfo contains details of the newly-established association.
          */
-        public abstract void onFailure(CharSequence error);
+        public void onAssociationCreated(@NonNull AssociationInfo associationInfo) {}
+
+        /**
+         * Invoked if the association could not be created.
+         *
+         * @param error error message.
+         */
+        public abstract void onFailure(@Nullable CharSequence error);
     }
 
     private final ICompanionDeviceManager mService;
     private Context mContext;
 
+    @GuardedBy("mListeners")
+    private final ArrayList<OnAssociationsChangedListenerProxy> mListeners = new ArrayList<>();
+
     /** @hide */
     public CompanionDeviceManager(
             @Nullable ICompanionDeviceManager service, @NonNull Context context) {
@@ -119,59 +230,109 @@
     }
 
     /**
-     * Associate this app with a companion device, selected by user
+     * Request to associate this app with a companion device.
      *
-     * <p>Once at least one appropriate device is found, {@code callback} will be called with a
-     * {@link PendingIntent} that can be used to show the list of available devices for the user
-     * to select.
-     * It should be started for result (i.e. using
-     * {@link android.app.Activity#startIntentSenderForResult}), as the resulting
-     * {@link android.content.Intent} will contain extra {@link #EXTRA_DEVICE}, with the selected
-     * device. (e.g. {@link android.bluetooth.BluetoothDevice})</p>
+     * <p>Note that before creating establishing association the system may need to show UI to
+     * collect user confirmation.</p>
      *
-     * <p>If your app needs to be excluded from battery optimizations (run in the background)
-     * or to have unrestricted data access (use data in the background) you can declare that
-     * you use the {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND} and {@link
-     * android.Manifest.permission#REQUEST_COMPANION_USE_DATA_IN_BACKGROUND} respectively. Note that these
-     * special capabilities have a negative effect on the device's battery and user's data
-     * usage, therefore you should request them when absolutely necessary.</p>
+     * <p>If the app needs to be excluded from battery optimizations (run in the background)
+     * or to have unrestricted data access (use data in the background) it should declare use of
+     * {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND} and
+     * {@link android.Manifest.permission#REQUEST_COMPANION_USE_DATA_IN_BACKGROUND} in its
+     * AndroidManifest.xml respectively.
+     * Note that these special capabilities have a negative effect on the device's battery and
+     * user's data usage, therefore you should request them when absolutely necessary.</p>
      *
-     * <p>You can call {@link #getAssociations} to get the list of currently associated
-     * devices, and {@link #disassociate} to remove an association. Consider doing so when the
-     * association is no longer relevant to avoid unnecessary battery and/or data drain resulting
-     * from special privileges that the association provides</p>
+     * <p>Application can use {@link #getMyAssociations()} for retrieving the list of currently
+     * {@link AssociationInfo} objects, that represent their existing associations.
+     * Applications can also use {@link #disassociate(int)} to remove an association, and are
+     * recommended to do when an association is no longer relevant to avoid unnecessary battery
+     * and/or data drain resulting from special privileges that the association provides</p>
      *
      * <p>Calling this API requires a uses-feature
      * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
+     **
+     * @param request A request object that describes details of the request.
+     * @param callback The callback used to notify application when the association is created.
+     * @param handler The handler which will be used to invoke the callback.
      *
-     * <p>When using {@link AssociationRequest#DEVICE_PROFILE_WATCH watch}
-     * {@link AssociationRequest.Builder#setDeviceProfile profile}, caller must also hold
-     * {@link Manifest.permission#REQUEST_COMPANION_PROFILE_WATCH}</p>
-     *
-     * @param request specific details about this request
-     * @param callback will be called once there's at least one device found for user to choose from
-     * @param handler A handler to control which thread the callback will be delivered on, or null,
-     *                to deliver it on main thread
-     *
-     * @see AssociationRequest
+     * @see AssociationRequest.Builder
+     * @see #getMyAssociations()
+     * @see #disassociate(int)
+     * @see #associate(AssociationRequest, Executor, Callback)
      */
-    @RequiresPermission(
-            value = Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH,
-            conditional = true)
+    @UserHandleAware
+    @RequiresPermission(anyOf = {
+            REQUEST_COMPANION_PROFILE_WATCH,
+            REQUEST_COMPANION_PROFILE_APP_STREAMING,
+            REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION,
+            }, conditional = true)
     public void associate(
             @NonNull AssociationRequest request,
             @NonNull Callback callback,
             @Nullable Handler handler) {
-        if (!checkFeaturePresent()) {
-            return;
-        }
+        if (!checkFeaturePresent()) return;
         Objects.requireNonNull(request, "Request cannot be null");
         Objects.requireNonNull(callback, "Callback cannot be null");
+        handler = Handler.mainIfNull(handler);
+
         try {
-            mService.associate(
-                    request,
-                    new CallbackProxy(request, callback, Handler.mainIfNull(handler)),
-                    getCallingPackage());
+            mService.associate(request, new AssociationRequestCallbackProxy(handler, callback),
+                    mContext.getOpPackageName(), mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Request to associate this app with a companion device.
+     *
+     * <p>Note that before creating establishing association the system may need to show UI to
+     * collect user confirmation.</p>
+     *
+     * <p>If the app needs to be excluded from battery optimizations (run in the background)
+     * or to have unrestricted data access (use data in the background) it should declare use of
+     * {@link android.Manifest.permission#REQUEST_COMPANION_RUN_IN_BACKGROUND} and
+     * {@link android.Manifest.permission#REQUEST_COMPANION_USE_DATA_IN_BACKGROUND} in its
+     * AndroidManifest.xml respectively.
+     * Note that these special capabilities have a negative effect on the device's battery and
+     * user's data usage, therefore you should request them when absolutely necessary.</p>
+     *
+     * <p>Application can use {@link #getMyAssociations()} for retrieving the list of currently
+     * {@link AssociationInfo} objects, that represent their existing associations.
+     * Applications can also use {@link #disassociate(int)} to remove an association, and are
+     * recommended to do when an association is no longer relevant to avoid unnecessary battery
+     * and/or data drain resulting from special privileges that the association provides</p>
+     *
+     * <p>Calling this API requires a uses-feature
+     * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
+     **
+     * @param request A request object that describes details of the request.
+     * @param executor The executor which will be used to invoke the callback.
+     * @param callback The callback used to notify application when the association is created.
+     *
+     * @see AssociationRequest.Builder
+     * @see #getMyAssociations()
+     * @see #disassociate(int)
+     */
+    @UserHandleAware
+    @RequiresPermission(anyOf = {
+            REQUEST_COMPANION_PROFILE_WATCH,
+            REQUEST_COMPANION_PROFILE_APP_STREAMING,
+            REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION
+            }, conditional = true)
+    public void associate(
+            @NonNull AssociationRequest request,
+            @NonNull Executor executor,
+            @NonNull Callback callback) {
+        if (!checkFeaturePresent()) return;
+        Objects.requireNonNull(request, "Request cannot be null");
+        Objects.requireNonNull(executor, "Executor cannot be null");
+        Objects.requireNonNull(callback, "Callback cannot be null");
+
+        try {
+            mService.associate(request, new AssociationRequestCallbackProxy(executor, callback),
+                    mContext.getOpPackageName(), mContext.getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -182,15 +343,32 @@
      * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
      *
      * @return a list of MAC addresses of devices that have been previously associated with the
-     * current app. You can use these with {@link #disassociate}
+     * current app are managed by CompanionDeviceManager (ie. does not include devices managed by
+     * application itself even if they have a MAC address).
+     *
+     * @deprecated use {@link #getMyAssociations()}
      */
+    @Deprecated
+    @UserHandleAware
     @NonNull
     public List<String> getAssociations() {
-        if (!checkFeaturePresent()) {
-            return Collections.emptyList();
-        }
+        return CollectionUtils.mapNotNull(getMyAssociations(),
+                a -> a.isSelfManaged() ? null : a.getDeviceMacAddressAsString());
+    }
+
+    /**
+     * <p>Calling this API requires a uses-feature
+     * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
+     *
+     * @return a list of associations that have been previously associated with the current app.
+     */
+    @UserHandleAware
+    @NonNull
+    public List<AssociationInfo> getMyAssociations() {
+        if (!checkFeaturePresent()) return Collections.emptyList();
+
         try {
-            return mService.getAssociations(getCallingPackage(), mContext.getUserId());
+            return mService.getAssociations(mContext.getOpPackageName(), mContext.getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -209,13 +387,41 @@
      * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
      *
      * @param deviceMacAddress the MAC address of device to disassociate from this app
+     *
+     * @deprecated use {@link #disassociate(int)}
      */
+    @UserHandleAware
+    @Deprecated
     public void disassociate(@NonNull String deviceMacAddress) {
-        if (!checkFeaturePresent()) {
-            return;
-        }
+        if (!checkFeaturePresent()) return;
+
         try {
-            mService.disassociate(deviceMacAddress, getCallingPackage());
+            mService.legacyDisassociate(deviceMacAddress, mContext.getOpPackageName(),
+                    mContext.getUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Remove an association.
+     *
+     * <p>Any privileges provided via being associated with a given device will be revoked</p>
+     *
+     * <p>Calling this API requires a uses-feature
+     * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
+     *
+     * @param associationId id of the association to be removed.
+     *
+     * @see #associate(AssociationRequest, Executor, Callback)
+     * @see AssociationInfo#getId()
+     */
+    @UserHandleAware
+    public void disassociate(int associationId) {
+        if (!checkFeaturePresent()) return;
+
+        try {
+            mService.disassociate(associationId);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -234,12 +440,14 @@
      * <p>Calling this API requires a uses-feature
      * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
      */
+    @UserHandleAware
     public void requestNotificationAccess(ComponentName component) {
         if (!checkFeaturePresent()) {
             return;
         }
         try {
-            IntentSender intentSender = mService.requestNotificationAccess(component)
+            IntentSender intentSender = mService
+                    .requestNotificationAccess(component, mContext.getUserId())
                     .getIntentSender();
             mContext.startIntentSender(intentSender, null, 0, 0, 0);
         } catch (RemoteException e) {
@@ -304,9 +512,7 @@
             @NonNull String packageName,
             @NonNull MacAddress macAddress,
             @NonNull UserHandle user) {
-        if (!checkFeaturePresent()) {
-            return false;
-        }
+        if (!checkFeaturePresent()) return false;
         Objects.requireNonNull(packageName, "package name cannot be null");
         Objects.requireNonNull(macAddress, "mac address cannot be null");
         Objects.requireNonNull(user, "user cannot be null");
@@ -322,21 +528,91 @@
      * Gets all package-device {@link AssociationInfo}s for the current user.
      *
      * @return the associations list
+     * @see #addOnAssociationsChangedListener(Executor, OnAssociationsChangedListener)
+     * @see #removeOnAssociationsChangedListener(OnAssociationsChangedListener)
      * @hide
      */
+    @SystemApi
+    @UserHandleAware
     @RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
     public @NonNull List<AssociationInfo> getAllAssociations() {
-        if (!checkFeaturePresent()) {
-            return Collections.emptyList();
-        }
+        if (!checkFeaturePresent()) return Collections.emptyList();
         try {
-            return mService.getAssociationsForUser(mContext.getUser().getIdentifier());
+            return mService.getAllAssociationsForUser(mContext.getUserId());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
+     * Listener for any changes to {@link AssociationInfo}.
+     *
+     * @hide
+     */
+    @SystemApi
+    public interface OnAssociationsChangedListener {
+        /**
+         * Invoked when a change occurs to any of the associations for the user (including adding
+         * new associations and removing existing associations).
+         *
+         * @param associations all existing associations for the user (after the change).
+         */
+        void onAssociationsChanged(@NonNull List<AssociationInfo> associations);
+    }
+
+    /**
+     * Register listener for any changes to {@link AssociationInfo}.
+     *
+     * @see #getAllAssociations()
+     * @hide
+     */
+    @SystemApi
+    @UserHandleAware
+    @RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
+    public void addOnAssociationsChangedListener(
+            @NonNull Executor executor, @NonNull OnAssociationsChangedListener listener) {
+        if (!checkFeaturePresent()) return;
+        synchronized (mListeners) {
+            final OnAssociationsChangedListenerProxy proxy = new OnAssociationsChangedListenerProxy(
+                    executor, listener);
+            try {
+                mService.addOnAssociationsChangedListener(proxy, mContext.getUserId());
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+            mListeners.add(proxy);
+        }
+    }
+
+    /**
+     * Unregister listener for any changes to {@link AssociationInfo}.
+     *
+     * @see #getAllAssociations()
+     * @hide
+     */
+    @SystemApi
+    @UserHandleAware
+    @RequiresPermission(android.Manifest.permission.MANAGE_COMPANION_DEVICES)
+    public void removeOnAssociationsChangedListener(
+            @NonNull OnAssociationsChangedListener listener) {
+        if (!checkFeaturePresent()) return;
+        synchronized (mListeners) {
+            final Iterator<OnAssociationsChangedListenerProxy> iterator = mListeners.iterator();
+            while (iterator.hasNext()) {
+                final OnAssociationsChangedListenerProxy proxy = iterator.next();
+                if (proxy.mListener == listener) {
+                    try {
+                        mService.removeOnAssociationsChangedListener(proxy, mContext.getUserId());
+                    } catch (RemoteException e) {
+                        throw e.rethrowFromSystemServer();
+                    }
+                    iterator.remove();
+                }
+            }
+        }
+    }
+
+    /**
      * Checks whether the bluetooth device represented by the mac address was recently associated
      * with the companion app. This allows these devices to skip the Bluetooth pairing dialog if
      * their pairing variant is {@link BluetoothDevice#PAIRING_VARIANT_CONSENT}.
@@ -404,8 +680,8 @@
         }
         Objects.requireNonNull(deviceAddress, "address cannot be null");
         try {
-            mService.registerDevicePresenceListenerService(
-                    mContext.getPackageName(), deviceAddress);
+            mService.registerDevicePresenceListenerService(deviceAddress,
+                    mContext.getOpPackageName(), mContext.getUserId());
         } catch (RemoteException e) {
             ExceptionUtils.propagateIfInstanceOf(e.getCause(), DeviceNotAssociatedException.class);
             throw e.rethrowFromSystemServer();
@@ -437,8 +713,8 @@
         }
         Objects.requireNonNull(deviceAddress, "address cannot be null");
         try {
-            mService.unregisterDevicePresenceListenerService(
-                    mContext.getPackageName(), deviceAddress);
+            mService.unregisterDevicePresenceListenerService(deviceAddress,
+                    mContext.getPackageName(), mContext.getUserId());
         } catch (RemoteException e) {
             ExceptionUtils.propagateIfInstanceOf(e.getCause(), DeviceNotAssociatedException.class);
         }
@@ -509,78 +785,63 @@
         return featurePresent;
     }
 
-    private Activity getActivity() {
-        return (Activity) mContext;
-    }
+    private static class AssociationRequestCallbackProxy extends IAssociationRequestCallback.Stub {
+        private final Handler mHandler;
+        private final Callback mCallback;
+        private final Executor mExecutor;
 
-    private String getCallingPackage() {
-        return mContext.getPackageName();
-    }
-
-    private class CallbackProxy extends IFindDeviceCallback.Stub
-            implements Application.ActivityLifecycleCallbacks {
-
-        private Callback mCallback;
-        private Handler mHandler;
-        private AssociationRequest mRequest;
-
-        final Object mLock = new Object();
-
-        private CallbackProxy(AssociationRequest request, Callback callback, Handler handler) {
+        private AssociationRequestCallbackProxy(
+                @NonNull Executor executor, @NonNull Callback callback) {
+            mExecutor = executor;
+            mHandler = null;
             mCallback = callback;
+        }
+
+        private AssociationRequestCallbackProxy(
+                @NonNull Handler handler, @NonNull Callback callback) {
             mHandler = handler;
-            mRequest = request;
-            getActivity().getApplication().registerActivityLifecycleCallbacks(this);
+            mExecutor = null;
+            mCallback = callback;
         }
 
         @Override
-        public void onSuccess(PendingIntent launcher) {
-            lockAndPost(Callback::onDeviceFound, launcher.getIntentSender());
+        public void onAssociationPending(@NonNull PendingIntent pi) {
+            execute(mCallback::onAssociationPending, pi.getIntentSender());
         }
 
         @Override
-        public void onFailure(CharSequence reason) {
-            lockAndPost(Callback::onFailure, reason);
+        public void onAssociationCreated(@NonNull AssociationInfo association) {
+            execute(mCallback::onAssociationCreated, association);
         }
 
-        <T> void lockAndPost(BiConsumer<Callback, T> action, T payload) {
-            synchronized (mLock) {
-                if (mHandler != null) {
-                    mHandler.post(() -> {
-                        Callback callback = null;
-                        synchronized (mLock) {
-                            callback = mCallback;
-                        }
-                        if (callback != null) {
-                            action.accept(callback, payload);
-                        }
-                    });
-                }
+        @Override
+        public void onFailure(CharSequence error) throws RemoteException {
+            execute(mCallback::onFailure, error);
+        }
+
+        private <T> void execute(Consumer<T> callback, T arg) {
+            if (mExecutor != null) {
+                mExecutor.execute(() -> callback.accept(arg));
+            } else {
+                mHandler.post(() -> callback.accept(arg));
             }
         }
+    }
 
-        @Override
-        public void onActivityDestroyed(Activity activity) {
-            synchronized (mLock) {
-                if (activity != getActivity()) return;
-                try {
-                    mService.stopScan(mRequest, this, getCallingPackage());
-                } catch (RemoteException e) {
-                    e.rethrowFromSystemServer();
-                }
-                getActivity().getApplication().unregisterActivityLifecycleCallbacks(this);
-                mCallback = null;
-                mHandler = null;
-                mRequest = null;
-                mContext = null;
-            }
+    private static class OnAssociationsChangedListenerProxy
+            extends IOnAssociationsChangedListener.Stub {
+        private final Executor mExecutor;
+        private final OnAssociationsChangedListener mListener;
+
+        private OnAssociationsChangedListenerProxy(Executor executor,
+                OnAssociationsChangedListener listener) {
+            mExecutor = executor;
+            mListener = listener;
         }
 
-        @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {}
-        @Override public void onActivityStarted(Activity activity) {}
-        @Override public void onActivityResumed(Activity activity) {}
-        @Override public void onActivityPaused(Activity activity) {}
-        @Override public void onActivityStopped(Activity activity) {}
-        @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {}
+        @Override
+        public void onAssociationsChanged(@NonNull List<AssociationInfo> associations) {
+            mExecutor.execute(() -> mListener.onAssociationsChanged(associations));
+        }
     }
 }
diff --git a/core/java/android/companion/DeviceId.java b/core/java/android/companion/DeviceId.java
deleted file mode 100644
index 5deed1a..0000000
--- a/core/java/android/companion/DeviceId.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2021 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 android.companion;
-
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.util.Objects;
-
-/**
- * The class represents free-form ID of a companion device.
- *
- * Since companion devices may have multiple IDs of different type at the same time
- * (eg. a MAC address and a Serial Number), this class not only stores the ID itself, it also stores
- * the type of the ID.
- * Both the type of the ID and its actual value are represented as {@link String}-s.
- *
- * Examples of device IDs:
- *  - "mac_address: f0:18:98:b3:fd:2e"
- *  - "ip_address: 128.121.35.200"
- *  - "imei: 352932100034923 / 44"
- *  - "serial_number: 96141FFAZ000B7"
- *  - "meid_hex: 35293210003492"
- *  - "meid_dic: 08918 92240 0001 3548"
- *
- * @hide
- * TODO(b/1979395): un-hide when implementing public APIs that use this class.
- */
-public final class DeviceId implements Parcelable {
-    public static final String TYPE_MAC_ADDRESS = "mac_address";
-
-    private final @NonNull String mType;
-    private final @NonNull String mValue;
-
-    /**
-     * @param type type of the ID. Non-empty. Max length - 16 characters.
-     * @param value the ID. Non-empty. Max length - 48 characters.
-     * @throws IllegalArgumentException if either {@param type} or {@param value} is empty or
-     *         exceeds its max allowed length.
-     */
-    public DeviceId(@NonNull String type, @NonNull String value) {
-        if (type.isEmpty() || value.isEmpty()) {
-            throw new IllegalArgumentException("'type' and 'value' should not be empty");
-        }
-        this.mType = type;
-        this.mValue = value;
-    }
-
-    /**
-     * @return the type of the ID.
-     */
-    public @NonNull String getType() {
-        return mType;
-    }
-
-    /**
-     * @return the ID.
-     */
-    public @NonNull String getValue() {
-        return mValue;
-    }
-
-    @Override
-    public String toString() {
-        return "DeviceId{"
-                + "type='" + mType + '\''
-                + ", value='" + mValue + '\''
-                + '}';
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof DeviceId)) return false;
-        DeviceId deviceId = (DeviceId) o;
-        return Objects.equals(mType, deviceId.mType) && Objects.equals(mValue,
-                deviceId.mValue);
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mType, mValue);
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeString(mType);
-        dest.writeString(mValue);
-    }
-
-    private DeviceId(@NonNull Parcel in) {
-        mType = in.readString();
-        mValue = in.readString();
-    }
-
-    public static final @NonNull Creator<DeviceId> CREATOR = new Creator<DeviceId>() {
-        @Override
-        public DeviceId createFromParcel(@NonNull Parcel in) {
-            return new DeviceId(in);
-        }
-
-        @Override
-        public DeviceId[] newArray(int size) {
-            return new DeviceId[size];
-        }
-    };
-}
diff --git a/core/java/android/companion/IFindDeviceCallback.aidl b/core/java/android/companion/IAssociationRequestCallback.aidl
similarity index 66%
copy from core/java/android/companion/IFindDeviceCallback.aidl
copy to core/java/android/companion/IAssociationRequestCallback.aidl
index a3a47a9..8cc2a71 100644
--- a/core/java/android/companion/IFindDeviceCallback.aidl
+++ b/core/java/android/companion/IAssociationRequestCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -17,10 +17,13 @@
 package android.companion;
 
 import android.app.PendingIntent;
+import android.companion.AssociationInfo;
 
 /** @hide */
-interface IFindDeviceCallback {
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    oneway void onSuccess(in PendingIntent launcher);
-    oneway void onFailure(in CharSequence reason);
-}
+interface IAssociationRequestCallback {
+    oneway void onAssociationPending(in PendingIntent pendingIntent);
+
+    oneway void onAssociationCreated(in AssociationInfo associationInfo);
+
+    oneway void onFailure(in CharSequence error);
+}
\ No newline at end of file
diff --git a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
index 71e5b24..702e8db 100644
--- a/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
+++ b/core/java/android/companion/ICompanionDeviceDiscoveryService.aidl
@@ -17,7 +17,7 @@
 package android.companion;
 
 import android.companion.AssociationRequest;
-import android.companion.IFindDeviceCallback;
+import android.companion.IAssociationRequestCallback;
 import com.android.internal.infra.AndroidFuture;
 
 
@@ -26,7 +26,7 @@
     void startDiscovery(
         in AssociationRequest request,
         in String callingPackage,
-        in IFindDeviceCallback findCallback,
+        in IAssociationRequestCallback applicationCallback,
         in AndroidFuture<String> serviceCallback);
 
     void onAssociationCreated();
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 101f948..1558db2 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -17,7 +17,8 @@
 package android.companion;
 
 import android.app.PendingIntent;
-import android.companion.IFindDeviceCallback;
+import android.companion.IAssociationRequestCallback;
+import android.companion.IOnAssociationsChangedListener;
 import android.companion.AssociationInfo;
 import android.companion.AssociationRequest;
 import android.content.ComponentName;
@@ -28,32 +29,41 @@
  * @hide
  */
 interface ICompanionDeviceManager {
-    void associate(in AssociationRequest request,
-        in IFindDeviceCallback callback,
-        in String callingPackage);
-    void stopScan(in AssociationRequest request,
-        in IFindDeviceCallback callback,
-        in String callingPackage);
+    void associate(in AssociationRequest request, in IAssociationRequestCallback callback,
+        in String callingPackage, int userId);
 
-    List<String> getAssociations(String callingPackage, int userId);
-    List<AssociationInfo> getAssociationsForUser(int userId);
+    List<AssociationInfo> getAssociations(String callingPackage, int userId);
+    List<AssociationInfo> getAllAssociationsForUser(int userId);
 
-    void disassociate(String deviceMacAddress, String callingPackage);
+    /** @deprecated */
+    void legacyDisassociate(String deviceMacAddress, String callingPackage, int userId);
 
+    void disassociate(int associationId);
+
+    /** @deprecated */
     boolean hasNotificationAccess(in ComponentName component);
-    PendingIntent requestNotificationAccess(in ComponentName component);
 
+    PendingIntent requestNotificationAccess(in ComponentName component, int userId);
+
+    /** @deprecated */
     boolean isDeviceAssociatedForWifiConnection(in String packageName, in String macAddress,
         int userId);
 
-    void registerDevicePresenceListenerService(in String packageName, in String deviceAddress);
+    void registerDevicePresenceListenerService(in String deviceAddress, in String callingPackage,
+        int userId);
 
-    void unregisterDevicePresenceListenerService(in String packageName, in String deviceAddress);
+    void unregisterDevicePresenceListenerService(in String deviceAddress, in String callingPackage,
+        int userId);
 
+    /** @deprecated */
     boolean canPairWithoutPrompt(in String packageName, in String deviceMacAddress, int userId);
 
+    /** @deprecated */
     void createAssociation(in String packageName, in String macAddress, int userId,
         in byte[] certificate);
 
     void dispatchMessage(in int messageId, in int associationId, in byte[] message);
+
+    void addOnAssociationsChangedListener(IOnAssociationsChangedListener listener, int userId);
+    void removeOnAssociationsChangedListener(IOnAssociationsChangedListener listener, int userId);
 }
diff --git a/core/java/android/companion/IFindDeviceCallback.aidl b/core/java/android/companion/IOnAssociationsChangedListener.aidl
similarity index 67%
rename from core/java/android/companion/IFindDeviceCallback.aidl
rename to core/java/android/companion/IOnAssociationsChangedListener.aidl
index a3a47a9..e6794b7 100644
--- a/core/java/android/companion/IFindDeviceCallback.aidl
+++ b/core/java/android/companion/IOnAssociationsChangedListener.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -16,11 +16,9 @@
 
 package android.companion;
 
-import android.app.PendingIntent;
+import android.companion.AssociationInfo;
 
 /** @hide */
-interface IFindDeviceCallback {
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    oneway void onSuccess(in PendingIntent launcher);
-    oneway void onFailure(in CharSequence reason);
-}
+interface IOnAssociationsChangedListener {
+    oneway void onAssociationsChanged(in List<AssociationInfo> associations);
+}
\ No newline at end of file
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 563b6cf..a9a2325 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -2664,6 +2664,38 @@
                 ContentProvider.getUserIdFromUri(uri, mContext.getUserId()));
     }
 
+    /**
+     * Same as {@link #registerContentObserver(Uri, boolean, ContentObserver)}, but the observer
+     * registered will get content change notifications from all users.
+     * {@link ContentObserver#onChange(boolean, Collection, int, UserHandle)} should be
+     * overwritten to get the corresponding {@link UserHandle} for that notification.
+     *
+     * @param uri                  The URI to watch for changes. This can be a specific row URI,
+     *                             or a base URI for a whole class of content.
+     * @param notifyForDescendants When false, the observer will be notified
+     *                             whenever a change occurs to the exact URI specified by
+     *                             <code>uri</code> or to one of the URI's ancestors in the path
+     *                             hierarchy. When true, the observer will also be notified
+     *                             whenever a change occurs to the URI's descendants in the path
+     *                             hierarchy.
+     * @param observer             The object that receives callbacks when changes occur.
+     * @hide
+     * @see #unregisterContentObserver
+     */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+    @SystemApi
+    public final void registerContentObserverForAllUsers(@NonNull Uri uri,
+            boolean notifyForDescendants,
+            @NonNull ContentObserver observer) {
+        Objects.requireNonNull(uri, "uri");
+        Objects.requireNonNull(observer, "observer");
+        registerContentObserver(
+                ContentProvider.getUriWithoutUserId(uri),
+                notifyForDescendants,
+                observer,
+                UserHandle.USER_ALL);
+    }
+
     /** @hide - designated user version */
     @UnsupportedAppUsage
     public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index e6df79e..2b75022 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3004,10 +3004,11 @@
      * {@link android.os.Build.VERSION_CODES#TIRAMISU},
      *              either {@link #RECEIVER_EXPORTED} or
      * {@link #RECEIVER_NOT_EXPORTED} must be specified if the receiver isn't being registered
-     *              for protected broadcasts or an exception will be thrown. If
+     *              for
+     *              <a href="https://developer.android.com/guide/components/broadcasts#system-broadcasts">system broadcasts</a> or an exception will be thrown. If
      *              {@link #RECEIVER_EXPORTED} is specified, a receiver may additionally
      *              specify {@link #RECEIVER_VISIBLE_TO_INSTANT_APPS}. For a complete list of
-     *              protected broadcast actions, see the BROADCAST_ACTIONS.TXT file in the
+     *              system broadcast actions, see the BROADCAST_ACTIONS.TXT file in the
      *              Android SDK. If both {@link #RECEIVER_EXPORTED} and
      *              {@link #RECEIVER_NOT_EXPORTED} are specified, an exception will be thrown as
      *              well.
@@ -3082,12 +3083,18 @@
      *      no permission is required.
      * @param scheduler Handler identifying the thread that will receive
      *      the Intent.  If null, the main thread of the process will be used.
-     * @param flags Additional options for the receiver. As of
-     * Android T, either {@link #RECEIVER_EXPORTED} or
+     * @param flags Additional options for the receiver. For apps targeting
+     * {@link android.os.Build.VERSION_CODES#TIRAMISU},
+     *              either {@link #RECEIVER_EXPORTED} or
      * {@link #RECEIVER_NOT_EXPORTED} must be specified if the receiver isn't being registered
-     *            for protected broadcasts, and may additionally specify
-     *            {@link #RECEIVER_VISIBLE_TO_INSTANT_APPS} if {@link #RECEIVER_EXPORTED} is
-     *            specified.
+     *              for
+     *              <a href="https://developer.android.com/guide/components/broadcasts#system-broadcasts">system broadcasts</a> or an exception will be thrown. If
+     *              {@link #RECEIVER_EXPORTED} is specified, a receiver may additionally
+     *              specify {@link #RECEIVER_VISIBLE_TO_INSTANT_APPS}. For a complete list of
+     *              system broadcast actions, see the BROADCAST_ACTIONS.TXT file in the
+     *              Android SDK. If both {@link #RECEIVER_EXPORTED} and
+     *              {@link #RECEIVER_NOT_EXPORTED} are specified, an exception will be thrown as
+     *              well.
      *
      * @return The first sticky intent found that matches <var>filter</var>,
      *         or null if there are none.
@@ -3146,10 +3153,18 @@
      *      no permission is required.
      * @param scheduler Handler identifying the thread that will receive
      *      the Intent. If {@code null}, the main thread of the process will be used.
-     * @param flags Additional options for the receiver. As of
-     *      Android T, either {@link #RECEIVER_EXPORTED} or
-     *      {@link #RECEIVER_NOT_EXPORTED} must be specified if the receiver isn't being
-     *      registered for protected broadcasts
+     * @param flags Additional options for the receiver. For apps targeting
+     * {@link android.os.Build.VERSION_CODES#TIRAMISU},
+     *              either {@link #RECEIVER_EXPORTED} or
+     * {@link #RECEIVER_NOT_EXPORTED} must be specified if the receiver isn't being registered
+     *              for
+     *              <a href="https://developer.android.com/guide/components/broadcasts#system-broadcasts">system broadcasts</a> or an exception will be thrown. If
+     *              {@link #RECEIVER_EXPORTED} is specified, a receiver may additionally
+     *              specify {@link #RECEIVER_VISIBLE_TO_INSTANT_APPS}. For a complete list of
+     *              system broadcast actions, see the BROADCAST_ACTIONS.TXT file in the
+     *              Android SDK. If both {@link #RECEIVER_EXPORTED} and
+     *              {@link #RECEIVER_NOT_EXPORTED} are specified, an exception will be thrown as
+     *              well.
      *
      * @return The first sticky intent found that matches <var>filter</var>,
      *         or {@code null} if there are none.
@@ -3213,10 +3228,18 @@
      *      no permission is required.
      * @param scheduler Handler identifying the thread that will receive
      *      the Intent.  If null, the main thread of the process will be used.
-     * @param flags Additional options for the receiver. As of
-     *      Android T, either {@link #RECEIVER_EXPORTED} or
-     *      {@link #RECEIVER_NOT_EXPORTED} must be specified if the receiver isn't being
-     *      registered for protected broadcasts
+     * @param flags Additional options for the receiver. For apps targeting
+     * {@link android.os.Build.VERSION_CODES#TIRAMISU},
+     *              either {@link #RECEIVER_EXPORTED} or
+     * {@link #RECEIVER_NOT_EXPORTED} must be specified if the receiver isn't being registered
+     *              for
+     *              <a href="https://developer.android.com/guide/components/broadcasts#system-broadcasts">system broadcasts</a> or an exception will be thrown. If
+     *              {@link #RECEIVER_EXPORTED} is specified, a receiver may additionally
+     *              specify {@link #RECEIVER_VISIBLE_TO_INSTANT_APPS}. For a complete list of
+     *              system broadcast actions, see the BROADCAST_ACTIONS.TXT file in the
+     *              Android SDK. If both {@link #RECEIVER_EXPORTED} and
+     *              {@link #RECEIVER_NOT_EXPORTED} are specified, an exception will be thrown as
+     *              well.
      *
      * @return The first sticky intent found that matches <var>filter</var>,
      *         or null if there are none.
@@ -3818,6 +3841,9 @@
             //@hide: SPEECH_RECOGNITION_SERVICE,
             UWB_SERVICE,
             MEDIA_METRICS_SERVICE,
+            SUPPLEMENTAL_PROCESS_SERVICE,
+            //@hide: ATTESTATION_VERIFICATION_SERVICE,
+            //@hide: SAFETY_CENTER_SERVICE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
@@ -5330,9 +5356,12 @@
      * {@link android.net.NetworkScoreManager} for managing network scoring.
      * @see #getSystemService(String)
      * @see android.net.NetworkScoreManager
+     * @deprecated see https://developer.android.com/guide/topics/connectivity/wifi-suggest for
+     * alternative API to propose WiFi networks.
      * @hide
      */
     @SystemApi
+    @Deprecated
     public static final String NETWORK_SCORE_SERVICE = "network_score";
 
     /**
@@ -5505,6 +5534,12 @@
     public static final String STATS_COMPANION_SERVICE = "statscompanion";
 
     /**
+     * Service to assist statsd in logging atoms from bootstrap atoms.
+     * @hide
+     */
+    public static final String STATS_BOOTSTRAP_ATOM_SERVICE = "statsbootstrap";
+
+    /**
      * Use with {@link #getSystemService(String)} to retrieve an {@link android.app.StatsManager}.
      * @hide
      */
@@ -5709,6 +5744,15 @@
 
     /**
      * Use with {@link #getSystemService(String)} to retrieve an
+     * {@link android.security.attestationverification.AttestationVerificationManager}.
+     * @see #getSystemService(String)
+     * @see android.security.attestationverification.AttestationVerificationManager
+     * @hide
+     */
+    public static final String ATTESTATION_VERIFICATION_SERVICE = "attestation_verification";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve an
      * {@link android.security.FileIntegrityManager}.
      * @see #getSystemService(String)
      * @see android.security.FileIntegrityManager
@@ -5834,6 +5878,34 @@
     public static final String LOCALE_SERVICE = "locale";
 
     /**
+     * Use with {@link #getSystemService(String)} to retrieve a Supplemental Process Manager.
+     *
+     * @see #getSystemService(String)
+     */
+    public static final String SUPPLEMENTAL_PROCESS_SERVICE = "supplemental_process";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a {@link
+     * android.safetycenter.SafetyCenterManager} instance for interacting with the safety center.
+     *
+     * @see #getSystemService(String)
+     * @see android.safetycenter.SafetyCenterManager
+     * @hide
+     */
+    @SystemApi
+    public static final String SAFETY_CENTER_SERVICE = "safety_center";
+
+    /**
+     * Use with {@link #getSystemService(String)} to retrieve a
+     * {@link android.nearby.NearbyManager} to discover nearby devices.
+     *
+     * @see #getSystemService(String)
+     * @see android.nearby.NearbyManager
+     * @hide
+     */
+    public static final String NEARBY_SERVICE = "nearby";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
@@ -6507,30 +6579,24 @@
             @NonNull Configuration overrideConfiguration);
 
     /**
-     * Return a new Context object for the current Context but whose resources
-     * are adjusted to match the metrics of the given Display.  Each call to this method
-     * returns a new instance of a Context object; Context objects are not
-     * shared, however common state (ClassLoader, other Resources for the
-     * same configuration) may be so the Context itself can be fairly lightweight.
-     *
-     * To obtain an instance of a {@link WindowManager} (see {@link #getSystemService(String)}) that
-     * is configured to show windows on the given display call
-     * {@link #createWindowContext(int, Bundle)} on the returned display Context or use an
-     * {@link android.app.Activity}.
-     *
+     * Returns a new <code>Context</code> object from the current context but with resources
+     * adjusted to match the metrics of <code>display</code>. Each call to this method
+     * returns a new instance of a context object. Context objects are not shared; however,
+     * common state (such as the {@link ClassLoader} and other resources for the same
+     * configuration) can be shared, so the <code>Context</code> itself is lightweight.
      * <p>
-     * Note that invoking #createDisplayContext(Display) from an UI context is not regarded
-     * as an UI context. In other words, it is not suggested to access UI components (such as
-     * obtain a {@link WindowManager} by {@link #getSystemService(String)})
-     * from the context created from #createDisplayContext(Display).
-     * </p>
+     * To obtain an instance of {@link WindowManager} configured to show windows on the given
+     * display, call {@link #createWindowContext(int, Bundle)} on the returned display context,
+     * then call {@link #getSystemService(String)} or {@link #getSystemService(Class)} on the
+     * returned window context.
+     * <p>
+     * <b>Note:</b> The context returned by <code>createDisplayContext(Display)</code> is not a UI
+     * context. Do not access UI components or obtain a {@link WindowManager} from the context
+     * created by <code>createDisplayContext(Display)</code>.
      *
-     * @param display A {@link Display} object specifying the display for whose metrics the
-     * Context's resources should be tailored.
+     * @param display The display to which the current context's resources are adjusted.
      *
-     * @return A {@link Context} for the display.
-     *
-     * @see #getSystemService(String)
+     * @return A context for the display.
      */
     @DisplayContext
     public abstract Context createDisplayContext(@NonNull Display display);
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 14e43b3..a36d532 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2378,6 +2378,14 @@
     public static final String ACTION_VIEW_APP_FEATURES =
             "android.intent.action.VIEW_APP_FEATURES";
 
+    /**
+     * Activity action: Launch UI to open the Safety Center, which highlights the user's security
+     * and privacy status.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_SAFETY_CENTER =
+            "android.intent.action.SAFETY_CENTER";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent broadcast actions (see action variable).
@@ -3152,9 +3160,8 @@
     /**
      * Broadcast Action: The receiver's effective locale has changed.
      *
-     * This happens when the device locale, or the
-     *  {(TODO: will only compile after ag/15518063) @link LocaleManager#setApplicationLocales}
-     *  receiving app's locale changed.
+     * This happens when the device locale, or the receiving app's locale
+     * (set via {@link android.app.LocaleManager#setApplicationLocales}) changed.
      *
      * Can be received by manifest-declared receivers.
      *
@@ -5523,8 +5530,8 @@
 
     /**
      * A boolean extra, when used with {@link #ACTION_VIEW_PERMISSION_USAGE_FOR_PERIOD},
-     * that specifies whether the system displayed attribution information in the
-     * permission usage system UI for the chosen entry.
+     * that specifies whether the permission usage system UI is showing attribution information
+     * for the chosen entry.
      *
      * <p> The extra can only be true if application has specified attributionsAreUserVisible
      * in its manifest. </p>
@@ -6416,6 +6423,7 @@
             FLAG_RECEIVER_FROM_SHELL,
             FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS,
             FLAG_RECEIVER_OFFLOAD,
+            FLAG_RECEIVER_OFFLOAD_FOREGROUND,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Flags {}
@@ -6461,6 +6469,7 @@
             FLAG_RECEIVER_FROM_SHELL,
             FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS,
             FLAG_RECEIVER_OFFLOAD,
+            FLAG_RECEIVER_OFFLOAD_FOREGROUND,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface MutableFlags {}
@@ -6915,6 +6924,13 @@
      */
     public static final int FLAG_RECEIVER_OFFLOAD = 0x80000000;
     /**
+     * If set, when sending a broadcast the recipient will run on the system dedicated queue.
+     *
+     * @hide
+     */
+    public static final int FLAG_RECEIVER_OFFLOAD_FOREGROUND = 0x00000800;
+
+    /**
      * If this is an ordered broadcast, don't allow receivers to abort the broadcast.
      * They can still propagate results through to later receivers, but they can not prevent
      * later receivers from seeing the broadcast.
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index f72288c..18e205f 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -18,6 +18,7 @@
 
 import android.content.pm.Checksum;
 import android.content.pm.DataLoaderParamsParcel;
+import android.content.pm.IOnChecksumsReadyListener;
 import android.content.pm.IPackageInstallObserver2;
 import android.content.IntentSender;
 import android.os.ParcelFileDescriptor;
@@ -36,6 +37,7 @@
     void stageViaHardLink(String target);
 
     void setChecksums(String name, in Checksum[] checksums, in byte[] signature);
+    void requestChecksums(in String name, int optional, int required, in List trustedInstallers, in IOnChecksumsReadyListener onChecksumsReadyListener);
 
     void removeSplit(String splitName);
 
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 27fb864..1c82b38 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -739,7 +739,7 @@
 
     void notifyPackagesReplacedReceived(in String[] packages);
 
-    void requestChecksums(in String packageName, boolean includeSplits, int optional, int required, in List trustedInstallers, in IOnChecksumsReadyListener onChecksumsReadyListener, int userId);
+    void requestPackageChecksums(in String packageName, boolean includeSplits, int optional, int required, in List trustedInstallers, in IOnChecksumsReadyListener onChecksumsReadyListener, int userId);
 
     IntentSender getLaunchIntentSenderForPackage(String packageName, String callingPackage,
                 String featureId, int userId);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 1586013..80584d1 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -19,6 +19,13 @@
 import static android.app.AppOpsManager.MODE_ALLOWED;
 import static android.app.AppOpsManager.MODE_DEFAULT;
 import static android.app.AppOpsManager.MODE_IGNORED;
+import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256;
+import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512;
+import static android.content.pm.Checksum.TYPE_WHOLE_MD5;
+import static android.content.pm.Checksum.TYPE_WHOLE_MERKLE_ROOT_4K_SHA256;
+import static android.content.pm.Checksum.TYPE_WHOLE_SHA1;
+import static android.content.pm.Checksum.TYPE_WHOLE_SHA256;
+import static android.content.pm.Checksum.TYPE_WHOLE_SHA512;
 
 import android.Manifest;
 import android.annotation.CurrentTimeMillisLong;
@@ -62,12 +69,16 @@
 import com.android.internal.util.function.pooled.PooledLambda;
 
 import java.io.Closeable;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.security.MessageDigest;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
@@ -406,6 +417,13 @@
     @Retention(RetentionPolicy.SOURCE)
     public @interface FileLocation{}
 
+    /** Default set of checksums - includes all available checksums.
+     * @see Session#requestChecksums  */
+    private static final int DEFAULT_CHECKSUMS =
+            TYPE_WHOLE_MERKLE_ROOT_4K_SHA256 | TYPE_WHOLE_MD5 | TYPE_WHOLE_SHA1 | TYPE_WHOLE_SHA256
+                    | TYPE_WHOLE_SHA512 | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256
+                    | TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512;
+
     private final IPackageInstaller mInstaller;
     private final int mUserId;
     private final String mInstallerPackageName;
@@ -1256,7 +1274,7 @@
          * @param name      previously written as part of this session.
          *                  {@link #openWrite}
          * @param checksums installer intends to make available via
-         *                  {@link PackageManager#requestChecksums}.
+         *                  {@link PackageManager#requestChecksums} or {@link #requestChecksums}.
          * @param signature DER PKCS#7 detached signature bytes over binary serialized checksums
          *                  to enable integrity checking for the checksums or null for no integrity
          *                  checking. {@link PackageManager#requestChecksums} will return
@@ -1293,6 +1311,89 @@
             }
         }
 
+        private static List<byte[]> encodeCertificates(List<Certificate> certs) throws
+                CertificateEncodingException {
+            if (certs == null) {
+                return null;
+            }
+            List<byte[]> result = new ArrayList<>(certs.size());
+            for (Certificate cert : certs) {
+                if (!(cert instanceof X509Certificate)) {
+                    throw new CertificateEncodingException("Only X509 certificates supported.");
+                }
+                result.add(cert.getEncoded());
+            }
+            return result;
+        }
+
+        /**
+         * Requests checksums for the APK file in session.
+         * <p>
+         * A possible use case is replying to {@link Intent#ACTION_PACKAGE_NEEDS_VERIFICATION}
+         * broadcast.
+         * The checksums will be returned asynchronously via onChecksumsReadyListener.
+         * <p>
+         * By default returns all readily available checksums:
+         * <ul>
+         * <li>enforced by platform,
+         * <li>enforced by the installer.
+         * </ul>
+         * If the caller needs a specific checksum type, they can specify it as required.
+         * <p>
+         * <b>Caution: Android can not verify installer-provided checksums. Make sure you specify
+         * trusted installers.</b>
+         * <p>
+         * @param name      previously written as part of this session.
+         *                  {@link #openWrite}
+         * @param required to explicitly request the checksum types. Will incur significant
+         *                 CPU/memory/disk usage.
+         * @param trustedInstallers for checksums enforced by installer, which installers are to be
+         *                          trusted.
+         *                          {@link PackageManager#TRUST_ALL} will return checksums from any
+         *                          installer,
+         *                          {@link PackageManager#TRUST_NONE} disables optimized
+         *                          installer-enforced checksums, otherwise the list has to be
+         *                          a non-empty list of certificates.
+         * @param onChecksumsReadyListener called once when the results are available.
+         * @throws CertificateEncodingException if an encoding error occurs for trustedInstallers.
+         * @throws FileNotFoundException if the file does not exist.
+         * @throws IllegalArgumentException if the list of trusted installer certificates is empty.
+         */
+        public void requestChecksums(@NonNull String name, @Checksum.TypeMask int required,
+                @NonNull List<Certificate> trustedInstallers,
+                @NonNull PackageManager.OnChecksumsReadyListener onChecksumsReadyListener)
+                throws CertificateEncodingException, FileNotFoundException {
+            Objects.requireNonNull(name);
+            Objects.requireNonNull(onChecksumsReadyListener);
+            Objects.requireNonNull(trustedInstallers);
+            if (trustedInstallers == PackageManager.TRUST_ALL) {
+                trustedInstallers = null;
+            } else if (trustedInstallers == PackageManager.TRUST_NONE) {
+                trustedInstallers = Collections.emptyList();
+            } else if (trustedInstallers.isEmpty()) {
+                throw new IllegalArgumentException(
+                        "trustedInstallers has to be one of TRUST_ALL/TRUST_NONE or a non-empty "
+                                + "list of certificates.");
+            }
+            try {
+                IOnChecksumsReadyListener onChecksumsReadyListenerDelegate =
+                        new IOnChecksumsReadyListener.Stub() {
+                            @Override
+                            public void onChecksumsReady(List<ApkChecksum> checksums)
+                                    throws RemoteException {
+                                onChecksumsReadyListener.onChecksumsReady(checksums);
+                            }
+                        };
+                mSession.requestChecksums(name, DEFAULT_CHECKSUMS, required,
+                        encodeCertificates(trustedInstallers), onChecksumsReadyListenerDelegate);
+            } catch (ParcelableException e) {
+                e.maybeRethrow(FileNotFoundException.class);
+                throw new RuntimeException(e);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
         /**
          * Attempt to commit everything staged in this session. This may require
          * user intervention, and so it may not happen immediately. The final
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 1b51314..c777bf5 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -9044,7 +9044,7 @@
     }
 
     /**
-     * Requesting the checksums for APKs within a package.
+     * Requests the checksums for APKs within a package.
      * The checksums will be returned asynchronously via onChecksumsReadyListener.
      *
      * By default returns all readily available checksums:
diff --git a/core/java/android/content/pm/PackagePartitions.java b/core/java/android/content/pm/PackagePartitions.java
index d157768..ff80e61 100644
--- a/core/java/android/content/pm/PackagePartitions.java
+++ b/core/java/android/content/pm/PackagePartitions.java
@@ -19,8 +19,11 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.Build;
+import android.os.Build.Partition;
 import android.os.Environment;
 import android.os.FileUtils;
+import android.os.SystemProperties;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -64,20 +67,34 @@
      */
     private static final ArrayList<SystemPartition> SYSTEM_PARTITIONS =
             new ArrayList<>(Arrays.asList(
-                    new SystemPartition(Environment.getRootDirectory(), PARTITION_SYSTEM,
+                    new SystemPartition(Environment.getRootDirectory(),
+                            PARTITION_SYSTEM, Partition.PARTITION_NAME_SYSTEM,
                             true /* containsPrivApp */, false /* containsOverlay */),
-                    new SystemPartition(Environment.getVendorDirectory(), PARTITION_VENDOR,
+                    new SystemPartition(Environment.getVendorDirectory(),
+                            PARTITION_VENDOR, Partition.PARTITION_NAME_VENDOR,
                             true /* containsPrivApp */, true /* containsOverlay */),
-                    new SystemPartition(Environment.getOdmDirectory(), PARTITION_ODM,
+                    new SystemPartition(Environment.getOdmDirectory(),
+                            PARTITION_ODM, Partition.PARTITION_NAME_ODM,
                             true /* containsPrivApp */, true /* containsOverlay */),
-                    new SystemPartition(Environment.getOemDirectory(), PARTITION_OEM,
+                    new SystemPartition(Environment.getOemDirectory(),
+                            PARTITION_OEM, Partition.PARTITION_NAME_OEM,
                             false /* containsPrivApp */, true /* containsOverlay */),
-                    new SystemPartition(Environment.getProductDirectory(), PARTITION_PRODUCT,
+                    new SystemPartition(Environment.getProductDirectory(),
+                            PARTITION_PRODUCT, Partition.PARTITION_NAME_PRODUCT,
                             true /* containsPrivApp */, true /* containsOverlay */),
-                    new SystemPartition(Environment.getSystemExtDirectory(), PARTITION_SYSTEM_EXT,
+                    new SystemPartition(Environment.getSystemExtDirectory(),
+                            PARTITION_SYSTEM_EXT, Partition.PARTITION_NAME_SYSTEM_EXT,
                             true /* containsPrivApp */, true /* containsOverlay */)));
 
     /**
+     * A string to represent the fingerprint of this build and all package partitions. Using it to
+     * determine whether the system update has occurred. Different from {@link Build#FINGERPRINT},
+     * this string is digested from the fingerprints of the build and all package partitions to
+     * help detect the partition update.
+     */
+    public static final String FINGERPRINT = getFingerprint();
+
+    /**
      * Returns a list in which the elements are products of the specified function applied to the
      * list of {@link #SYSTEM_PARTITIONS} in increasing specificity order.
      */
@@ -101,6 +118,23 @@
         }
     }
 
+    /**
+     * Returns a fingerprint string for this build and all package partitions. The string is
+     * digested from the fingerprints of the build and all package partitions.
+     *
+     * @return A string to represent the fingerprint of this build and all package partitions.
+     */
+    @NonNull
+    private static String getFingerprint() {
+        final String[] digestProperties = new String[SYSTEM_PARTITIONS.size() + 1];
+        for (int i = 0; i < SYSTEM_PARTITIONS.size(); i++) {
+            final String partitionName = SYSTEM_PARTITIONS.get(i).getName();
+            digestProperties[i] = "ro." + partitionName + ".build.fingerprint";
+        }
+        digestProperties[SYSTEM_PARTITIONS.size()] = "ro.build.fingerprint"; // build fingerprint
+        return SystemProperties.digestOf(digestProperties);
+    }
+
     /** Represents a partition that contains application packages. */
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
     public static class SystemPartition {
@@ -108,6 +142,9 @@
         public final int type;
 
         @NonNull
+        private final String mName;
+
+        @NonNull
         private final DeferredCanonicalFile mFolder;
 
         @Nullable
@@ -122,9 +159,10 @@
         @NonNull
         private final File mNonConicalFolder;
 
-        private SystemPartition(@NonNull File folder, @PartitionType int type,
+        private SystemPartition(@NonNull File folder, @PartitionType int type, String name,
                 boolean containsPrivApp, boolean containsOverlay) {
             this.type = type;
+            this.mName = name;
             this.mFolder = new DeferredCanonicalFile(folder);
             this.mAppFolder = new DeferredCanonicalFile(folder, "app");
             this.mPrivAppFolder = containsPrivApp ? new DeferredCanonicalFile(folder, "priv-app")
@@ -136,6 +174,7 @@
 
         public SystemPartition(@NonNull SystemPartition original) {
             this.type = original.type;
+            this.mName = original.mName;
             this.mFolder = new DeferredCanonicalFile(original.mFolder.getFile());
             this.mAppFolder = original.mAppFolder;
             this.mPrivAppFolder = original.mPrivAppFolder;
@@ -148,10 +187,19 @@
          * different root folder.
          */
         public SystemPartition(@NonNull File rootFolder, @NonNull SystemPartition partition) {
-            this(rootFolder, partition.type, partition.mPrivAppFolder != null,
+            this(rootFolder, partition.type, partition.mName, partition.mPrivAppFolder != null,
                     partition.mOverlayFolder != null);
         }
 
+        /**
+         * Returns the name identifying the partition.
+         * @see Partition
+         */
+        @NonNull
+        public String getName() {
+            return mName;
+        }
+
         /** Returns the canonical folder of the partition. */
         @NonNull
         public File getFolder() {
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index cc4782a..aa57806 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -10,6 +10,9 @@
       "path": "frameworks/base/services/tests/PackageManagerComponentOverrideTests"
     },
     {
+      "path": "frameworks/base/services/tests/servicestests/src/com/android/server/pm"
+    },
+    {
       "path": "cts/tests/tests/packageinstaller"
     },
     {
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index 14d69cc..056f99f 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -362,6 +362,9 @@
 
     ParsingPackage setAttributionsAreUserVisible(boolean attributionsAreUserVisible);
 
+    ParsingPackage setResetEnabledSettingsOnAppDataCleared(
+            boolean resetEnabledSettingsOnAppDataCleared);
+
     // TODO(b/135203078): This class no longer has access to ParsedPackage, find a replacement
     //  for moving to the next step
     @CallSuper
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
index edddf40..d5957a2 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageImpl.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -334,7 +334,7 @@
     @DataClass.ParcelWith(ForInternedString.class)
     private String backupAgentName;
     private int banner;
-    private int category;
+    private int category = ApplicationInfo.CATEGORY_UNDEFINED;
     @Nullable
     @DataClass.ParcelWith(ForInternedString.class)
     private String classLoaderName;
@@ -517,6 +517,7 @@
         private static final long DISALLOW_PROFILING = 1L << 45;
         private static final long REQUEST_FOREGROUND_SERVICE_EXEMPTION = 1L << 46;
         private static final long ATTRIBUTIONS_ARE_USER_VISIBLE = 1L << 47;
+        private static final long RESET_ENABLED_SETTINGS_ON_APP_DATA_CLEARED = 1L << 48;
     }
 
     private ParsingPackageImpl setBoolean(@Booleans.Values long flag, boolean value) {
@@ -2216,6 +2217,11 @@
     }
 
     @Override
+    public boolean isResetEnabledSettingsOnAppDataCleared() {
+        return getBoolean(Booleans.RESET_ENABLED_SETTINGS_ON_APP_DATA_CLEARED);
+    }
+
+    @Override
     public ParsingPackageImpl setBaseRevisionCode(int value) {
         baseRevisionCode = value;
         return this;
@@ -2771,4 +2777,12 @@
         setBoolean(Booleans.ATTRIBUTIONS_ARE_USER_VISIBLE, attributionsAreUserVisible);
         return this;
     }
+
+    @Override
+    public ParsingPackage setResetEnabledSettingsOnAppDataCleared(
+            boolean resetEnabledSettingsOnAppDataCleared) {
+        setBoolean(Booleans.RESET_ENABLED_SETTINGS_ON_APP_DATA_CLEARED,
+                resetEnabledSettingsOnAppDataCleared);
+        return this;
+    }
 }
diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java
index 4a249bb..2933f95 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageRead.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java
@@ -297,4 +297,12 @@
      * @see R.styleable#AndroidManifestService_visibleToInstantApps
      */
     boolean isVisibleToInstantApps();
+
+    /**
+     * Whether the enabled settings of components in the application should be reset to the default,
+     * when the application's user data is cleared.
+     *
+     * @see R.styleable#AndroidManifestApplication_resetEnabledSettingsOnAppDataCleared
+     */
+    boolean isResetEnabledSettingsOnAppDataCleared();
 }
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
index e3a5de5..d2ac8739 100644
--- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -2288,6 +2288,9 @@
                 .setVmSafeMode(bool(false, R.styleable.AndroidManifestApplication_vmSafeMode, sa))
                 .setAutoRevokePermissions(anInt(R.styleable.AndroidManifestApplication_autoRevokePermissions, sa))
                 .setAttributionsAreUserVisible(bool(false, R.styleable.AndroidManifestApplication_attributionsAreUserVisible, sa))
+                .setResetEnabledSettingsOnAppDataCleared(bool(false,
+                    R.styleable.AndroidManifestApplication_resetEnabledSettingsOnAppDataCleared,
+                    sa))
                 // targetSdkVersion gated
                 .setAllowAudioPlaybackCapture(bool(targetSdk >= Build.VERSION_CODES.Q, R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture, sa))
                 .setBaseHardwareAccelerated(bool(targetSdk >= Build.VERSION_CODES.ICE_CREAM_SANDWICH, R.styleable.AndroidManifestApplication_hardwareAccelerated, sa))
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 8ebb8ec..01bf49e 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -2432,27 +2432,10 @@
                 break;
         }
 
-        switch (config.uiMode & Configuration.UI_MODE_TYPE_MASK) {
-            case Configuration.UI_MODE_TYPE_APPLIANCE:
-                parts.add("appliance");
-                break;
-            case Configuration.UI_MODE_TYPE_DESK:
-                parts.add("desk");
-                break;
-            case Configuration.UI_MODE_TYPE_TELEVISION:
-                parts.add("television");
-                break;
-            case Configuration.UI_MODE_TYPE_CAR:
-                parts.add("car");
-                break;
-            case Configuration.UI_MODE_TYPE_WATCH:
-                parts.add("watch");
-                break;
-            case Configuration.UI_MODE_TYPE_VR_HEADSET:
-                parts.add("vrheadset");
-                break;
-            default:
-                break;
+        final String uiModeTypeString =
+                getUiModeTypeString(config.uiMode & Configuration.UI_MODE_TYPE_MASK);
+        if (uiModeTypeString != null) {
+            parts.add(uiModeTypeString);
         }
 
         switch (config.uiMode & Configuration.UI_MODE_NIGHT_MASK) {
@@ -2587,6 +2570,28 @@
     }
 
     /**
+     * @hide
+     */
+    public static String getUiModeTypeString(int uiModeType) {
+        switch (uiModeType) {
+            case Configuration.UI_MODE_TYPE_APPLIANCE:
+                return "appliance";
+            case Configuration.UI_MODE_TYPE_DESK:
+                return "desk";
+            case Configuration.UI_MODE_TYPE_TELEVISION:
+                return "television";
+            case Configuration.UI_MODE_TYPE_CAR:
+                return "car";
+            case Configuration.UI_MODE_TYPE_WATCH:
+                return "watch";
+            case Configuration.UI_MODE_TYPE_VR_HEADSET:
+                return "vrheadset";
+            default:
+                return null;
+        }
+    }
+
+    /**
      * Generate a delta Configuration between <code>base</code> and <code>change</code>. The
      * resulting delta can be used with {@link #updateFrom(Configuration)}.
      * <p />
diff --git a/core/java/android/database/ContentObserver.java b/core/java/android/database/ContentObserver.java
index 578d53b..c27ee51 100644
--- a/core/java/android/database/ContentObserver.java
+++ b/core/java/android/database/ContentObserver.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemApi;
 import android.annotation.UserIdInt;
 import android.app.compat.CompatChanges;
 import android.compat.annotation.ChangeId;
@@ -188,6 +189,27 @@
         }
     }
 
+    /**
+     * This method is called when a content change occurs. Includes the changed
+     * content Uris when available.
+     * <p>
+     * Subclasses should override this method to handle content changes. To
+     * ensure correct operation on older versions of the framework that did not
+     * provide richer arguments, applications should implement all overloads.
+     *
+     * @param selfChange True if this is a self-change notification.
+     * @param uris The Uris of the changed content.
+     * @param flags Flags indicating details about this change.
+     * @param user The corresponding {@link UserHandle} for the current notification.
+     *
+     * @hide
+     */
+    @SystemApi
+    public void onChange(boolean selfChange, @NonNull Collection<Uri> uris,
+            @NotifyFlags int flags, @NonNull UserHandle user) {
+        onChange(selfChange, uris, user.getIdentifier());
+    }
+
     /** @hide */
     public void onChange(boolean selfChange, @NonNull Collection<Uri> uris,
             @NotifyFlags int flags, @UserIdInt int userId) {
@@ -197,7 +219,7 @@
         if (!CompatChanges.isChangeEnabled(ADD_CONTENT_OBSERVER_FLAGS)
                 || android.os.Process.myUid() == android.os.Process.SYSTEM_UID) {
             // Deliver userId through argument to preserve hidden API behavior
-            onChange(selfChange, uris, userId);
+            onChange(selfChange, uris, flags, UserHandle.of(userId));
         } else {
             onChange(selfChange, uris, flags);
         }
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 96a18dc..3c8b6e9 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -1323,7 +1323,7 @@
      * <p>Maximum flashlight brightness level.</p>
      * <p>If this value is greater than 1, then the device supports controlling the
      * flashlight brightness level via
-     * {android.hardware.camera2.CameraManager#setTorchStrengthLevel}.
+     * {android.hardware.camera2.CameraManager#turnOnTorchWithStrengthLevel}.
      * If this value is equal to 1, flashlight brightness control is not supported.
      * The value for this key will be null for devices with no flash unit.</p>
      * <p><b>Optional</b> - The value for this key may be {@code null} on some devices.</p>
@@ -1335,7 +1335,7 @@
 
     /**
      * <p>Default flashlight brightness level to be set via
-     * {android.hardware.camera2.CameraManager#setTorchStrengthLevel}.</p>
+     * {android.hardware.camera2.CameraManager#turnOnTorchWithStrengthLevel}.</p>
      * <p>If flash unit is available this will be greater than or equal to 1 and less
      * or equal to <code>{@link CameraCharacteristics#FLASH_INFO_STRENGTH_MAXIMUM_LEVEL android.flash.info.strengthMaximumLevel}</code>.</p>
      * <p>Setting flashlight brightness above the default level
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 8864939..9b19fc4 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -110,6 +110,11 @@
     private int mRepeatingRequestId = REQUEST_ID_NONE;
     // Latest repeating request list's types
     private int[] mRepeatingRequestTypes;
+
+    // Cache failed requests to process later in case of a repeating error callback
+    private int mFailedRepeatingRequestId = REQUEST_ID_NONE;
+    private int[] mFailedRepeatingRequestTypes;
+
     // Map stream IDs to input/output configurations
     private SimpleEntry<Integer, InputConfiguration> mConfiguredInput =
             new SimpleEntry<>(REQUEST_ID_NONE, null);
@@ -1326,16 +1331,25 @@
 
                 int requestId = mRepeatingRequestId;
                 mRepeatingRequestId = REQUEST_ID_NONE;
+                mFailedRepeatingRequestId = REQUEST_ID_NONE;
                 int[] requestTypes = mRepeatingRequestTypes;
                 mRepeatingRequestTypes = null;
+                mFailedRepeatingRequestTypes = null;
 
                 long lastFrameNumber;
                 try {
                     lastFrameNumber = mRemoteDevice.cancelRequest(requestId);
                 } catch (IllegalArgumentException e) {
                     if (DEBUG) {
-                        Log.v(TAG, "Repeating request was already stopped for request " + requestId);
+                        Log.v(TAG, "Repeating request was already stopped for request " +
+                                requestId);
                     }
+                    // Cache request id and request types in case of a race with
+                    // "onRepeatingRequestError" which may no yet be scheduled on another thread
+                    // or blocked by us.
+                    mFailedRepeatingRequestId = requestId;
+                    mFailedRepeatingRequestTypes = requestTypes;
+
                     // Repeating request was already stopped. Nothing more to do.
                     return;
                 }
@@ -1965,7 +1979,17 @@
             synchronized(mInterfaceLock) {
                 // Camera is already closed or no repeating request is present.
                 if (mRemoteDevice == null || mRepeatingRequestId == REQUEST_ID_NONE) {
-                    return; // Camera already closed
+                    if ((mFailedRepeatingRequestId == repeatingRequestId) &&
+                            (mFailedRepeatingRequestTypes != null) && (mRemoteDevice != null)) {
+                        Log.v(TAG, "Resuming stop of failed repeating request with id: " +
+                                mFailedRepeatingRequestId);
+
+                        checkEarlyTriggerSequenceCompleteLocked(mFailedRepeatingRequestId,
+                                lastFrameNumber, mFailedRepeatingRequestTypes);
+                        mFailedRepeatingRequestId = REQUEST_ID_NONE;
+                        mFailedRepeatingRequestTypes = null;
+                    }
+                    return;
                 }
 
                 // Redirect device callback to the offline session in case we are in the middle
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java
index 95892aa..b06d076 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManager.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManager.java
@@ -96,7 +96,7 @@
     public void requestState(@NonNull DeviceStateRequest request,
             @Nullable @CallbackExecutor Executor executor,
             @Nullable DeviceStateRequest.Callback callback) {
-        mGlobal.requestState(request, callback, executor);
+        mGlobal.requestState(request, executor, callback);
     }
 
     /**
diff --git a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
index 904a54b..85e70b0 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
@@ -117,7 +117,7 @@
      * @see DeviceStateRequest
      */
     public void requestState(@NonNull DeviceStateRequest request,
-            @Nullable DeviceStateRequest.Callback callback, @Nullable Executor executor) {
+            @Nullable Executor executor, @Nullable DeviceStateRequest.Callback callback) {
         if (callback == null && executor != null) {
             throw new IllegalArgumentException("Callback must be supplied with executor.");
         } else if (executor == null && callback != null) {
@@ -149,7 +149,7 @@
 
     /**
      * Cancels a {@link DeviceStateRequest request} previously submitted with a call to
-     * {@link #requestState(DeviceStateRequest, DeviceStateRequest.Callback, Executor)}.
+     * {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
      *
      * @see DeviceStateManager#cancelRequest(DeviceStateRequest)
      */
@@ -408,7 +408,7 @@
                 return;
             }
 
-            mExecutor.execute(() -> mCallback.onRequestSuspended(mRequest));
+            mExecutor.execute(() -> mCallback.onRequestCanceled(mRequest));
         }
     }
 }
diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
index 2b52e96..0b1ed65 100644
--- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java
+++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
@@ -109,7 +109,10 @@
 
     /** {@hide} */
     public boolean quickPickupSensorEnabled(int user) {
-        return !TextUtils.isEmpty(quickPickupSensorType()) && !alwaysOnEnabled(user);
+        return boolSettingDefaultOn(Settings.Secure.DOZE_QUICK_PICKUP_GESTURE, user)
+                && !TextUtils.isEmpty(quickPickupSensorType())
+                && pickupGestureEnabled(user)
+                && !alwaysOnEnabled(user);
     }
 
     /** {@hide} */
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 5bb51c1..2985c75 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.graphics.Point;
 import android.hardware.SensorManager;
+import android.media.projection.IMediaProjection;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.PowerManager;
@@ -30,6 +31,7 @@
 import android.view.DisplayInfo;
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Transaction;
+import android.window.DisplayWindowPolicyController;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -372,6 +374,46 @@
     public abstract Point getDisplaySurfaceDefaultSize(int displayId);
 
     /**
+     * Receives early interactivity changes from power manager.
+     *
+     * @param interactive The interactive state that the device is moving into.
+     */
+    public abstract void onEarlyInteractivityChange(boolean interactive);
+
+    /**
+     * A special API for creates a virtual display with a DisplayPolicyController in system_server.
+     * <p>
+     * If this method is called without original calling uid, the caller must enforce the
+     * corresponding permissions according to the flags.
+     *   {@link android.Manifest.permission#CAPTURE_VIDEO_OUTPUT}
+     *   {@link android.Manifest.permission#CAPTURE_SECURE_VIDEO_OUTPUT}
+     *   {@link android.Manifest.permission#ADD_TRUSTED_DISPLAY}
+     *   {@link android.Manifest.permission#INTERNAL_SYSTEM_WINDOW}
+     * </p>
+     *
+     * @param virtualDisplayConfig The arguments for the virtual display configuration. See
+     *                             {@link VirtualDisplayConfig} for using it.
+     * @param callback Callback to call when the virtual display's state changes, or null if none.
+     * @param projection MediaProjection token.
+     * @param packageName The package name of the app.
+     * @param controller The DisplayWindowPolicyControl that can control what contents are
+     *                   allowed to be displayed.
+     * @return The newly created virtual display id , or {@link Display#INVALID_DISPLAY} if the
+     * virtual display cannot be created.
+     */
+    public abstract int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
+            IVirtualDisplayCallback callback, IMediaProjection projection, String packageName,
+            DisplayWindowPolicyController controller);
+
+    /**
+     * Get {@link DisplayWindowPolicyController} associated to the {@link DisplayInfo#displayId}
+     *
+     * @param displayId The id of the display.
+     * @return The associated {@link DisplayWindowPolicyController}.
+     */
+    public abstract DisplayWindowPolicyController getDisplayWindowPolicyController(int displayId);
+
+    /**
      * Describes the requested power state of the display.
      *
      * This object is intended to describe the general characteristics of the
diff --git a/core/java/android/hardware/input/InputDeviceVibrator.java b/core/java/android/hardware/input/InputDeviceVibrator.java
index 653c622..ce6b523 100644
--- a/core/java/android/hardware/input/InputDeviceVibrator.java
+++ b/core/java/android/hardware/input/InputDeviceVibrator.java
@@ -174,8 +174,8 @@
      * @hide
      */
     @Override
-    public void vibrate(int uid, String opPkg, @NonNull VibrationEffect effect,
-            String reason, @NonNull VibrationAttributes attributes) {
+    public void vibrate(int uid, String opPkg, @NonNull VibrationEffect effect, String reason,
+            @NonNull VibrationAttributes attributes) {
         mInputManager.vibrate(mDeviceId, effect, mToken);
     }
 
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index e5d8620..6f0c944 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -1016,9 +1016,8 @@
     }
 
     /**
-     * Queries the framework about whether any physical keys exist on the
-     * any keyboard attached to the device that are capable of producing the given
-     * array of key codes.
+     * Queries the framework about whether any physical keys exist on any currently attached input
+     * devices that are capable of producing the given array of key codes.
      *
      * @param keyCodes The array of key codes to query.
      * @return A new array of the same size as the key codes array whose elements
@@ -1032,11 +1031,10 @@
     }
 
     /**
-     * Queries the framework about whether any physical keys exist on the
-     * any keyboard attached to the device that are capable of producing the given
-     * array of key codes.
+     * Queries the framework about whether any physical keys exist on the specified input device
+     * that are capable of producing the given array of key codes.
      *
-     * @param id The id of the device to query.
+     * @param id The id of the input device to query or -1 to consult all devices.
      * @param keyCodes The array of key codes to query.
      * @return A new array of the same size as the key codes array whose elements are set to true
      * if the given device could produce the corresponding key code at the same index in the key
diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java
index 5cd4eb5..5e0e1b7 100644
--- a/core/java/android/net/NetworkKey.java
+++ b/core/java/android/net/NetworkKey.java
@@ -35,8 +35,10 @@
 /**
  * Information which identifies a specific network.
  *
+ * @deprecated as part of the {@link NetworkScoreManager} deprecation.
  * @hide
  */
+@Deprecated
 @SystemApi
 // NOTE: Ideally, we would abstract away the details of what identifies a network of a specific
 // type, so that all networks appear the same and can be scored without concern to the network type
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
index 0ba2663..7b8b5c0 100644
--- a/core/java/android/net/NetworkScoreManager.java
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -51,9 +51,13 @@
  *     permission.
  * </ul>
  *
+ * @deprecated No longer functional on {@link android.os.Build.VERSION_CODES#TIRAMISU} and above.
+ * See https://developer.android.com/guide/topics/connectivity/wifi-suggest for
+ * alternative APIs to suggest/configure Wi-Fi networks.
  * @hide
  */
 @SystemApi
+@Deprecated
 @SystemService(Context.NETWORK_SCORE_SERVICE)
 public class NetworkScoreManager {
     private static final String TAG = "NetworkScoreManager";
@@ -245,7 +249,7 @@
      *                           or {@link permission#REQUEST_NETWORK_SCORES} permissions.
      */
     @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
-                                 android.Manifest.permission.REQUEST_NETWORK_SCORES})
+            android.Manifest.permission.REQUEST_NETWORK_SCORES})
     public String getActiveScorerPackage() {
         try {
             return mService.getActiveScorerPackage();
@@ -322,7 +326,7 @@
      *                           hold the {@link permission#REQUEST_NETWORK_SCORES} permission.
      */
     @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
-                                 android.Manifest.permission.REQUEST_NETWORK_SCORES})
+            android.Manifest.permission.REQUEST_NETWORK_SCORES})
     public boolean clearScores() throws SecurityException {
         try {
             return mService.clearScores();
@@ -344,7 +348,7 @@
      */
     @SystemApi
     @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
-                                 android.Manifest.permission.REQUEST_NETWORK_SCORES})
+            android.Manifest.permission.REQUEST_NETWORK_SCORES})
     public boolean setActiveScorer(String packageName) throws SecurityException {
         try {
             return mService.setActiveScorer(packageName);
@@ -362,7 +366,7 @@
      *                           hold the {@link permission#REQUEST_NETWORK_SCORES} permission.
      */
     @RequiresPermission(anyOf = {android.Manifest.permission.SCORE_NETWORKS,
-                                 android.Manifest.permission.REQUEST_NETWORK_SCORES})
+            android.Manifest.permission.REQUEST_NETWORK_SCORES})
     public void disableScoring() throws SecurityException {
         try {
             mService.disableScoring();
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index ee24084..c906a13 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -70,9 +70,17 @@
     private static final String TAG = "NetworkTemplate";
 
     /**
+     * Initial Version of the backup serializer.
+     */
+    public static final int BACKUP_VERSION_1_INIT = 1;
+    /**
+     * Version of the backup serializer that added carrier template support.
+     */
+    public static final int BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE = 2;
+    /**
      * Current Version of the Backup Serializer.
      */
-    private static final int BACKUP_VERSION = 1;
+    private static final int BACKUP_VERSION = BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE;
 
     public static final int MATCH_MOBILE = 1;
     public static final int MATCH_WIFI = 4;
@@ -285,6 +293,10 @@
     private final int mRoaming;
     private final int mDefaultNetwork;
     private final int mSubType;
+    /**
+     * The subscriber Id match rule defines how the template should match networks with
+     * specific subscriberId(s). See NetworkTemplate#SUBSCRIBER_ID_MATCH_RULE_* for more detail.
+     */
     private final int mSubscriberIdMatchRule;
 
     // Bitfield containing OEM network properties{@code NetworkIdentity#OEM_*}.
@@ -348,7 +360,7 @@
         mSubscriberIdMatchRule = subscriberIdMatchRule;
         checkValidSubscriberIdMatchRule();
         if (!isKnownMatchRule(matchRule)) {
-            Log.e(TAG, "Unknown network template rule " + matchRule
+            throw new IllegalArgumentException("Unknown network template rule " + matchRule
                     + " will not match any identity.");
         }
     }
@@ -842,11 +854,17 @@
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
         DataOutputStream out = new DataOutputStream(baos);
 
+        if (!isPersistable()) {
+            Log.wtf(TAG, "Trying to backup non-persistable template: " + this);
+        }
+
         out.writeInt(BACKUP_VERSION);
 
         out.writeInt(mMatchRule);
         BackupUtils.writeString(out, mSubscriberId);
         BackupUtils.writeString(out, mNetworkId);
+        out.writeInt(mMetered);
+        out.writeInt(mSubscriberIdMatchRule);
 
         return baos.toByteArray();
     }
@@ -854,7 +872,7 @@
     public static NetworkTemplate getNetworkTemplateFromBackup(DataInputStream in)
             throws IOException, BackupUtils.BadVersionException {
         int version = in.readInt();
-        if (version < 1 || version > BACKUP_VERSION) {
+        if (version < BACKUP_VERSION_1_INIT || version > BACKUP_VERSION) {
             throw new BackupUtils.BadVersionException("Unknown Backup Serialization Version");
         }
 
@@ -862,11 +880,27 @@
         String subscriberId = BackupUtils.readString(in);
         String networkId = BackupUtils.readString(in);
 
-        if (!isKnownMatchRule(matchRule)) {
-            throw new BackupUtils.BadVersionException(
-                    "Restored network template contains unknown match rule " + matchRule);
+        final int metered;
+        final int subscriberIdMatchRule;
+        if (version >= BACKUP_VERSION_2_SUPPORT_CARRIER_TEMPLATE) {
+            metered = in.readInt();
+            subscriberIdMatchRule = in.readInt();
+        } else {
+            // For backward compatibility, fill the missing filters from match rules.
+            metered = (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD
+                    || matchRule == MATCH_CARRIER) ? METERED_YES : METERED_ALL;
+            subscriberIdMatchRule = SUBSCRIBER_ID_MATCH_RULE_EXACT;
         }
 
-        return new NetworkTemplate(matchRule, subscriberId, networkId);
+        try {
+            return new NetworkTemplate(matchRule,
+                    subscriberId, new String[] { subscriberId },
+                    networkId, metered, NetworkStats.ROAMING_ALL,
+                    NetworkStats.DEFAULT_NETWORK_ALL, NetworkTemplate.NETWORK_TYPE_ALL,
+                    NetworkTemplate.OEM_MANAGED_ALL, subscriberIdMatchRule);
+        } catch (IllegalArgumentException e) {
+            throw new BackupUtils.BadVersionException(
+                    "Restored network template contains unknown match rule " + matchRule, e);
+        }
     }
 }
diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java
index 668e966..02cafb5 100644
--- a/core/java/android/net/RssiCurve.java
+++ b/core/java/android/net/RssiCurve.java
@@ -50,8 +50,10 @@
  * the system.
  *
  * @see ScoredNetwork
+ * @deprecated as part of the {@link NetworkScoreManager} deprecation.
  * @hide
  */
+@Deprecated
 @SystemApi
 public class RssiCurve implements Parcelable {
     private static final int DEFAULT_ACTIVE_NETWORK_RSSI_BOOST = 25;
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
index 64b3bf1..a46bdd9a 100644
--- a/core/java/android/net/ScoredNetwork.java
+++ b/core/java/android/net/ScoredNetwork.java
@@ -29,8 +29,10 @@
 /**
  * A network identifier along with a score for the quality of that network.
  *
+ * @deprecated as part of the {@link NetworkScoreManager} deprecation.
  * @hide
  */
+@Deprecated
 @SystemApi
 public class ScoredNetwork implements Parcelable {
 
diff --git a/core/java/android/net/WifiKey.java b/core/java/android/net/WifiKey.java
index bc9d8c5..2e4ea89 100644
--- a/core/java/android/net/WifiKey.java
+++ b/core/java/android/net/WifiKey.java
@@ -29,8 +29,10 @@
  * Information identifying a Wi-Fi network.
  * @see NetworkKey
  *
+ * @deprecated as part of the {@link NetworkScore} deprecation.
  * @hide
  */
+@Deprecated
 @SystemApi
 public class WifiKey implements Parcelable {
 
diff --git a/core/java/android/net/nsd/INsdManager.aidl b/core/java/android/net/nsd/INsdManager.aidl
index e9e8935..89e9cdb 100644
--- a/core/java/android/net/nsd/INsdManager.aidl
+++ b/core/java/android/net/nsd/INsdManager.aidl
@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2012, The Android Open Source Project
+ * Copyright (c) 2021, 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.
@@ -16,16 +16,15 @@
 
 package android.net.nsd;
 
+import android.net.nsd.INsdManagerCallback;
+import android.net.nsd.INsdServiceConnector;
 import android.os.Messenger;
 
 /**
- * Interface that NsdService implements
+ * Interface that NsdService implements to connect NsdManager clients.
  *
  * {@hide}
  */
-interface INsdManager
-{
-    @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553)
-    Messenger getMessenger();
-    void setEnabled(boolean enable);
+interface INsdManager {
+    INsdServiceConnector connect(INsdManagerCallback cb);
 }
diff --git a/core/java/android/net/nsd/INsdManagerCallback.aidl b/core/java/android/net/nsd/INsdManagerCallback.aidl
new file mode 100644
index 0000000..1a262ec
--- /dev/null
+++ b/core/java/android/net/nsd/INsdManagerCallback.aidl
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2021, 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 android.net.nsd;
+
+import android.os.Messenger;
+import android.net.nsd.NsdServiceInfo;
+
+/**
+ * Callbacks from NsdService to NsdManager
+ * @hide
+ */
+oneway interface INsdManagerCallback {
+    void onDiscoverServicesStarted(int listenerKey, in NsdServiceInfo info);
+    void onDiscoverServicesFailed(int listenerKey, int error);
+    void onServiceFound(int listenerKey, in NsdServiceInfo info);
+    void onServiceLost(int listenerKey, in NsdServiceInfo info);
+    void onStopDiscoveryFailed(int listenerKey, int error);
+    void onStopDiscoverySucceeded(int listenerKey);
+    void onRegisterServiceFailed(int listenerKey, int error);
+    void onRegisterServiceSucceeded(int listenerKey, in NsdServiceInfo info);
+    void onUnregisterServiceFailed(int listenerKey, int error);
+    void onUnregisterServiceSucceeded(int listenerKey);
+    void onResolveServiceFailed(int listenerKey, int error);
+    void onResolveServiceSucceeded(int listenerKey, in NsdServiceInfo info);
+}
diff --git a/core/java/android/net/nsd/INsdServiceConnector.aidl b/core/java/android/net/nsd/INsdServiceConnector.aidl
new file mode 100644
index 0000000..b06ae55
--- /dev/null
+++ b/core/java/android/net/nsd/INsdServiceConnector.aidl
@@ -0,0 +1,35 @@
+/**
+ * Copyright (c) 2021, 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 android.net.nsd;
+
+import android.net.nsd.INsdManagerCallback;
+import android.net.nsd.NsdServiceInfo;
+import android.os.Messenger;
+
+/**
+ * Interface that NsdService implements for each NsdManager client.
+ *
+ * {@hide}
+ */
+interface INsdServiceConnector {
+    void registerService(int listenerKey, in NsdServiceInfo serviceInfo);
+    void unregisterService(int listenerKey);
+    void discoverServices(int listenerKey, in NsdServiceInfo serviceInfo);
+    void stopDiscovery(int listenerKey);
+    void resolveService(int listenerKey, in NsdServiceInfo serviceInfo);
+    void startDaemon();
+}
\ No newline at end of file
diff --git a/core/java/android/net/nsd/NsdManager.java b/core/java/android/net/nsd/NsdManager.java
index ae8d010..6c597e2 100644
--- a/core/java/android/net/nsd/NsdManager.java
+++ b/core/java/android/net/nsd/NsdManager.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -31,17 +31,13 @@
 import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Messenger;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 
-import java.util.concurrent.CountDownLatch;
-
 /**
  * The Network Service Discovery Manager class provides the API to discover services
  * on a network. As an example, if device A and device B are connected over a Wi-Fi
@@ -234,6 +230,11 @@
     /** @hide */
     public static final int NATIVE_DAEMON_EVENT                     = BASE + 26;
 
+    /** @hide */
+    public static final int REGISTER_CLIENT                         = BASE + 27;
+    /** @hide */
+    public static final int UNREGISTER_CLIENT                       = BASE + 28;
+
     /** Dns based service discovery protocol */
     public static final int PROTOCOL_DNS_SD = 0x0001;
 
@@ -274,7 +275,7 @@
 
     private static final int FIRST_LISTENER_KEY = 1;
 
-    private final INsdManager mService;
+    private final INsdServiceConnector mService;
     private final Context mContext;
 
     private int mListenerKey = FIRST_LISTENER_KEY;
@@ -282,9 +283,7 @@
     private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<>();
     private final Object mMapLock = new Object();
 
-    private final AsyncChannel mAsyncChannel = new AsyncChannel();
-    private ServiceHandler mHandler;
-    private final CountDownLatch mConnected = new CountDownLatch(1);
+    private final ServiceHandler mHandler;
 
     /**
      * Create a new Nsd instance. Applications use
@@ -295,18 +294,108 @@
      * is a system private class.
      */
     public NsdManager(Context context, INsdManager service) {
-        mService = service;
         mContext = context;
-        init();
+
+        HandlerThread t = new HandlerThread("NsdManager");
+        t.start();
+        mHandler = new ServiceHandler(t.getLooper());
+
+        try {
+            mService = service.connect(new NsdCallbackImpl(mHandler));
+        } catch (RemoteException e) {
+            throw new RuntimeException("Failed to connect to NsdService");
+        }
+
+        // Only proactively start the daemon if the target SDK < S, otherwise the internal service
+        // would automatically start/stop the native daemon as needed.
+        if (!CompatChanges.isChangeEnabled(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)) {
+            try {
+                mService.startDaemon();
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to proactively start daemon");
+                // Continue: the daemon can still be started on-demand later
+            }
+        }
     }
 
-    /**
-     * @hide
-     */
-    @VisibleForTesting
-    public void disconnect() {
-        mAsyncChannel.disconnect();
-        mHandler.getLooper().quitSafely();
+    private static class NsdCallbackImpl extends INsdManagerCallback.Stub {
+        private final Handler mServHandler;
+
+        NsdCallbackImpl(Handler serviceHandler) {
+            mServHandler = serviceHandler;
+        }
+
+        private void sendInfo(int message, int listenerKey, NsdServiceInfo info) {
+            mServHandler.sendMessage(mServHandler.obtainMessage(message, 0, listenerKey, info));
+        }
+
+        private void sendError(int message, int listenerKey, int error) {
+            mServHandler.sendMessage(mServHandler.obtainMessage(message, error, listenerKey));
+        }
+
+        private void sendNoArg(int message, int listenerKey) {
+            mServHandler.sendMessage(mServHandler.obtainMessage(message, 0, listenerKey));
+        }
+
+        @Override
+        public void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) {
+            sendInfo(DISCOVER_SERVICES_STARTED, listenerKey, info);
+        }
+
+        @Override
+        public void onDiscoverServicesFailed(int listenerKey, int error) {
+            sendError(DISCOVER_SERVICES_FAILED, listenerKey, error);
+        }
+
+        @Override
+        public void onServiceFound(int listenerKey, NsdServiceInfo info) {
+            sendInfo(SERVICE_FOUND, listenerKey, info);
+        }
+
+        @Override
+        public void onServiceLost(int listenerKey, NsdServiceInfo info) {
+            sendInfo(SERVICE_LOST, listenerKey, info);
+        }
+
+        @Override
+        public void onStopDiscoveryFailed(int listenerKey, int error) {
+            sendError(STOP_DISCOVERY_FAILED, listenerKey, error);
+        }
+
+        @Override
+        public void onStopDiscoverySucceeded(int listenerKey) {
+            sendNoArg(STOP_DISCOVERY_SUCCEEDED, listenerKey);
+        }
+
+        @Override
+        public void onRegisterServiceFailed(int listenerKey, int error) {
+            sendError(REGISTER_SERVICE_FAILED, listenerKey, error);
+        }
+
+        @Override
+        public void onRegisterServiceSucceeded(int listenerKey, NsdServiceInfo info) {
+            sendInfo(REGISTER_SERVICE_SUCCEEDED, listenerKey, info);
+        }
+
+        @Override
+        public void onUnregisterServiceFailed(int listenerKey, int error) {
+            sendError(UNREGISTER_SERVICE_FAILED, listenerKey, error);
+        }
+
+        @Override
+        public void onUnregisterServiceSucceeded(int listenerKey) {
+            sendNoArg(UNREGISTER_SERVICE_SUCCEEDED, listenerKey);
+        }
+
+        @Override
+        public void onResolveServiceFailed(int listenerKey, int error) {
+            sendError(RESOLVE_SERVICE_FAILED, listenerKey, error);
+        }
+
+        @Override
+        public void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) {
+            sendInfo(RESOLVE_SERVICE_SUCCEEDED, listenerKey, info);
+        }
     }
 
     /**
@@ -376,19 +465,6 @@
         public void handleMessage(Message message) {
             final int what = message.what;
             final int key = message.arg2;
-            switch (what) {
-                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
-                    mAsyncChannel.sendMessage(AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
-                    return;
-                case AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED:
-                    mConnected.countDown();
-                    return;
-                case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
-                    Log.e(TAG, "Channel lost");
-                    return;
-                default:
-                    break;
-            }
             final Object listener;
             final NsdServiceInfo ns;
             synchronized (mMapLock) {
@@ -504,36 +580,6 @@
     }
 
     /**
-     * Initialize AsyncChannel
-     */
-    private void init() {
-        final Messenger messenger = getMessenger();
-        if (messenger == null) {
-            fatal("Failed to obtain service Messenger");
-        }
-        HandlerThread t = new HandlerThread("NsdManager");
-        t.start();
-        mHandler = new ServiceHandler(t.getLooper());
-        mAsyncChannel.connect(mContext, mHandler, messenger);
-        try {
-            mConnected.await();
-        } catch (InterruptedException e) {
-            fatal("Interrupted wait at init");
-        }
-        if (CompatChanges.isChangeEnabled(RUN_NATIVE_NSD_ONLY_IF_LEGACY_APPS)) {
-            return;
-        }
-        // Only proactively start the daemon if the target SDK < S, otherwise the internal service
-        // would automatically start/stop the native daemon as needed.
-        mAsyncChannel.sendMessage(DAEMON_STARTUP);
-    }
-
-    private static void fatal(String msg) {
-        Log.e(TAG, msg);
-        throw new RuntimeException(msg);
-    }
-
-    /**
      * Register a service to be discovered by other services.
      *
      * <p> The function call immediately returns after sending a request to register service
@@ -556,7 +602,11 @@
         checkServiceInfo(serviceInfo);
         checkProtocol(protocolType);
         int key = putListener(listener, serviceInfo);
-        mAsyncChannel.sendMessage(REGISTER_SERVICE, 0, key, serviceInfo);
+        try {
+            mService.registerService(key, serviceInfo);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -574,7 +624,11 @@
      */
     public void unregisterService(RegistrationListener listener) {
         int id = getListenerKey(listener);
-        mAsyncChannel.sendMessage(UNREGISTER_SERVICE, 0, id);
+        try {
+            mService.unregisterService(id);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -613,7 +667,11 @@
         s.setServiceType(serviceType);
 
         int key = putListener(listener, s);
-        mAsyncChannel.sendMessage(DISCOVER_SERVICES, 0, key, s);
+        try {
+            mService.discoverServices(key, s);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -634,7 +692,11 @@
      */
     public void stopServiceDiscovery(DiscoveryListener listener) {
         int id = getListenerKey(listener);
-        mAsyncChannel.sendMessage(STOP_DISCOVERY, 0, id);
+        try {
+            mService.stopDiscovery(id);
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
     }
 
     /**
@@ -649,29 +711,10 @@
     public void resolveService(NsdServiceInfo serviceInfo, ResolveListener listener) {
         checkServiceInfo(serviceInfo);
         int key = putListener(listener, serviceInfo);
-        mAsyncChannel.sendMessage(RESOLVE_SERVICE, 0, key, serviceInfo);
-    }
-
-    /** Internal use only @hide */
-    public void setEnabled(boolean enabled) {
         try {
-            mService.setEnabled(enabled);
+            mService.resolveService(key, serviceInfo);
         } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    /**
-     * Get a reference to NsdService handler. This is used to establish
-     * an AsyncChannel communication with the service
-     *
-     * @return Messenger pointing to the NsdService handler
-     */
-    private Messenger getMessenger() {
-        try {
-            return mService.getMessenger();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
+            e.rethrowFromSystemServer();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt b/core/java/android/net/nsd/NsdServiceInfo.aidl
similarity index 84%
copy from packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
copy to core/java/android/net/nsd/NsdServiceInfo.aidl
index bacc66b..657bdd1 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
+++ b/core/java/android/net/nsd/NsdServiceInfo.aidl
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.flags
+package android.net.nsd;
 
-interface FlagWriter {
-    fun setEnabled(key: Int, value: Boolean) {}
-}
\ No newline at end of file
+@JavaOnlyStableParcelable parcelable NsdServiceInfo;
\ No newline at end of file
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 0af322e..0954013 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -528,6 +528,7 @@
     public String toString() {
         StringBuilder out = new StringBuilder("ApduService: ");
         out.append(getComponent());
+        out.append(", UID: " + mUid);
         out.append(", description: " + mDescription);
         out.append(", Static AID Groups: ");
         for (AidGroup aidGroup : mStaticAidGroups.values()) {
@@ -546,7 +547,8 @@
         if (!(o instanceof ApduServiceInfo)) return false;
         ApduServiceInfo thatService = (ApduServiceInfo) o;
 
-        return thatService.getComponent().equals(this.getComponent());
+        return thatService.getComponent().equals(this.getComponent())
+                && thatService.getUid() == this.getUid();
     }
 
     @Override
@@ -619,8 +621,9 @@
     };
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("    " + getComponent() +
-                " (Description: " + getDescription() + ")");
+        pw.println("    " + getComponent()
+                + " (Description: " + getDescription() + ")"
+                + " (UID: " + getUid() + ")");
         if (mOnHost) {
             pw.println("    On Host Service");
         } else {
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index d498535..0a9fe90 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -30,6 +30,7 @@
 import android.nfc.INfcCardEmulation;
 import android.nfc.NfcAdapter;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
 import android.util.Log;
@@ -83,6 +84,13 @@
     public static final String EXTRA_SERVICE_COMPONENT = "component";
 
     /**
+     * The caller userId extra for {@link #ACTION_CHANGE_DEFAULT}.
+     *
+     * @see #ACTION_CHANGE_DEFAULT
+     */
+    public static final String EXTRA_USERID = "android.nfc.cardemulation.extra.USERID";
+
+    /**
      * Category used for NFC payment services.
      */
     public static final String CATEGORY_PAYMENT = "payment";
@@ -269,8 +277,8 @@
         if (CATEGORY_PAYMENT.equals(category)) {
             boolean preferForeground = false;
             try {
-                preferForeground = Settings.Secure.getInt(mContext.getContentResolver(),
-                        Settings.Secure.NFC_PAYMENT_FOREGROUND) != 0;
+                preferForeground = Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                        Settings.Secure.NFC_PAYMENT_FOREGROUND, UserHandle.myUserId()) != 0;
             } catch (SettingNotFoundException e) {
             }
             return preferForeground;
@@ -829,6 +837,28 @@
     /**
      * @hide
      */
+    public boolean setDefaultForNextTap(int userId, ComponentName service) {
+        try {
+            return sService.setDefaultForNextTap(userId, service);
+        } catch (RemoteException e) {
+            // Try one more time
+            recoverService();
+            if (sService == null) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return false;
+            }
+            try {
+                return sService.setDefaultForNextTap(userId, service);
+            } catch (RemoteException ee) {
+                Log.e(TAG, "Failed to reach CardEmulationService.");
+                return false;
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
     public List<ApduServiceInfo> getServices(String category) {
         try {
             return sService.getServices(mContext.getUserId(), category);
@@ -849,6 +879,28 @@
     }
 
     /**
+     * @hide
+     */
+    public List<ApduServiceInfo> getServices(String category, int userId) {
+        try {
+            return sService.getServices(userId, category);
+        } catch (RemoteException e) {
+            // Try one more time
+            recoverService();
+            if (sService == null) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return null;
+            }
+            try {
+                return sService.getServices(userId, category);
+            } catch (RemoteException ee) {
+                Log.e(TAG, "Failed to reach CardEmulationService.");
+                return null;
+            }
+        }
+    }
+
+    /**
      * A valid AID according to ISO/IEC 7816-4:
      * <ul>
      * <li>Has >= 5 bytes and <=16 bytes (>=10 hex chars and <= 32 hex chars)
diff --git a/core/java/android/nfc/cardemulation/NfcFCardEmulation.java b/core/java/android/nfc/cardemulation/NfcFCardEmulation.java
index 80e8579..557e41a 100644
--- a/core/java/android/nfc/cardemulation/NfcFCardEmulation.java
+++ b/core/java/android/nfc/cardemulation/NfcFCardEmulation.java
@@ -25,7 +25,6 @@
 import android.nfc.INfcFCardEmulation;
 import android.nfc.NfcAdapter;
 import android.os.RemoteException;
-import android.os.UserHandle;
 import android.util.Log;
 
 import java.util.HashMap;
diff --git a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
index c2b33dd..f8f7dfe 100644
--- a/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/NfcFServiceInfo.java
@@ -237,6 +237,7 @@
     public String toString() {
         StringBuilder out = new StringBuilder("NfcFService: ");
         out.append(getComponent());
+        out.append(", UID: " + mUid);
         out.append(", description: " + mDescription);
         out.append(", System Code: " + mSystemCode);
         if (mDynamicSystemCode != null) {
@@ -257,6 +258,7 @@
         NfcFServiceInfo thatService = (NfcFServiceInfo) o;
 
         if (!thatService.getComponent().equals(this.getComponent())) return false;
+        if (thatService.getUid() != this.getUid()) return false;
         if (!thatService.mSystemCode.equalsIgnoreCase(this.mSystemCode)) return false;
         if (!thatService.mNfcid2.equalsIgnoreCase(this.mNfcid2)) return false;
         if (!thatService.mT3tPmm.equalsIgnoreCase(this.mT3tPmm)) return false;
@@ -321,8 +323,9 @@
     };
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("    " + getComponent() +
-                " (Description: " + getDescription() + ")");
+        pw.println("    " + getComponent()
+                + " (Description: " + getDescription() + ")"
+                + " (UID: " + getUid() + ")");
         pw.println("    System Code: " + getSystemCode());
         pw.println("    NFCID2: " + getNfcid2());
         pw.println("    T3tPmm: " + getT3tPmm());
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 689c806..53484d2 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -58,6 +58,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.text.DecimalFormat;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Formatter;
@@ -859,11 +860,13 @@
         /**
          * Returns cpu times of an uid at a particular process state.
          */
-        public abstract long[] getCpuFreqTimes(int which, int procState);
+        public abstract boolean getCpuFreqTimes(@NonNull long[] timesInFreqMs, int procState);
+
         /**
          * Returns cpu times of an uid while the screen if off at a particular process state.
          */
-        public abstract long[] getScreenOffCpuFreqTimes(int which, int procState);
+        public abstract boolean getScreenOffCpuFreqTimes(@NonNull long[] timesInFreqMs,
+                int procState);
 
         // Note: the following times are disjoint.  They can be added together to find the
         // total time a uid has had any processes running at all.
@@ -1575,6 +1578,11 @@
 
     public abstract long getNextMaxDailyDeadline();
 
+    /**
+     * Returns the total number of frequencies across all CPU clusters.
+     */
+    public abstract int getCpuFreqCount();
+
     public abstract long[] getCpuFreqs();
 
     public final static class HistoryTag {
@@ -4626,27 +4634,26 @@
                             cpuFreqTimeMs.length, sb.toString());
                 }
 
+                final long[] timesInFreqMs = new long[getCpuFreqCount()];
                 for (int procState = 0; procState < Uid.NUM_PROCESS_STATE; ++procState) {
-                    final long[] timesMs = u.getCpuFreqTimes(which, procState);
-                    if (timesMs != null && timesMs.length == cpuFreqs.length) {
+                    if (u.getCpuFreqTimes(timesInFreqMs, procState)) {
                         sb.setLength(0);
-                        for (int i = 0; i < timesMs.length; ++i) {
+                        for (int i = 0; i < timesInFreqMs.length; ++i) {
                             if (i != 0) sb.append(',');
-                            sb.append(timesMs[i]);
+                            sb.append(timesInFreqMs[i]);
                         }
-                        final long[] screenOffTimesMs = u.getScreenOffCpuFreqTimes(
-                                which, procState);
-                        if (screenOffTimesMs != null) {
-                            for (int i = 0; i < screenOffTimesMs.length; ++i) {
-                                sb.append(',').append(screenOffTimesMs[i]);
+                        if (u.getScreenOffCpuFreqTimes(timesInFreqMs, procState)) {
+                            for (int i = 0; i < timesInFreqMs.length; ++i) {
+                                sb.append(',').append(timesInFreqMs[i]);
                             }
                         } else {
-                            for (int i = 0; i < timesMs.length; ++i) {
+                            for (int i = 0; i < timesInFreqMs.length; ++i) {
                                 sb.append(",0");
                             }
                         }
                         dumpLine(pw, uid, category, CPU_TIMES_AT_FREQ_DATA,
-                                Uid.UID_PROCESS_TYPES[procState], timesMs.length, sb.toString());
+                                Uid.UID_PROCESS_TYPES[procState], timesInFreqMs.length,
+                                sb.toString());
                     }
                 }
             }
@@ -6243,25 +6250,24 @@
                 pw.println(sb.toString());
             }
 
+            final long[] timesInFreqMs = new long[getCpuFreqCount()];
             for (int procState = 0; procState < Uid.NUM_PROCESS_STATE; ++procState) {
-                final long[] cpuTimes = u.getCpuFreqTimes(which, procState);
-                if (cpuTimes != null) {
+                if (u.getCpuFreqTimes(timesInFreqMs, procState)) {
                     sb.setLength(0);
                     sb.append("    Cpu times per freq at state ")
                             .append(Uid.PROCESS_STATE_NAMES[procState]).append(':');
-                    for (int i = 0; i < cpuTimes.length; ++i) {
-                        sb.append(" " + cpuTimes[i]);
+                    for (int i = 0; i < timesInFreqMs.length; ++i) {
+                        sb.append(" ").append(timesInFreqMs[i]);
                     }
                     pw.println(sb.toString());
                 }
 
-                final long[] screenOffCpuTimes = u.getScreenOffCpuFreqTimes(which, procState);
-                if (screenOffCpuTimes != null) {
+                if (u.getScreenOffCpuFreqTimes(timesInFreqMs, procState)) {
                     sb.setLength(0);
                     sb.append("   Screen-off cpu times per freq at state ")
                             .append(Uid.PROCESS_STATE_NAMES[procState]).append(':');
-                    for (int i = 0; i < screenOffCpuTimes.length; ++i) {
-                        sb.append(" " + screenOffCpuTimes[i]);
+                    for (int i = 0; i < timesInFreqMs.length; ++i) {
+                        sb.append(" ").append(timesInFreqMs[i]);
                     }
                     pw.println(sb.toString());
                 }
@@ -7348,9 +7354,11 @@
                         pw.print(getHistoryTagPoolUid(i));
                         pw.print(",\"");
                         String str = getHistoryTagPoolString(i);
-                        str = str.replace("\\", "\\\\");
-                        str = str.replace("\"", "\\\"");
-                        pw.print(str);
+                        if (str != null) {
+                            str = str.replace("\\", "\\\\");
+                            str = str.replace("\"", "\\\"");
+                            pw.print(str);
+                        }
                         pw.print("\"");
                         pw.println();
                     }
@@ -7627,22 +7635,22 @@
                 }
             }
 
+            final long[] timesInFreqMs = new long[getCpuFreqCount()];
+            final long[] timesInFreqScreenOffMs = new long[getCpuFreqCount()];
             for (int procState = 0; procState < Uid.NUM_PROCESS_STATE; ++procState) {
-                final long[] timesMs = u.getCpuFreqTimes(which, procState);
-                if (timesMs != null && timesMs.length == cpuFreqs.length) {
-                    long[] screenOffTimesMs = u.getScreenOffCpuFreqTimes(which, procState);
-                    if (screenOffTimesMs == null) {
-                        screenOffTimesMs = new long[timesMs.length];
+                if (u.getCpuFreqTimes(timesInFreqMs, procState)) {
+                    if (!u.getScreenOffCpuFreqTimes(timesInFreqScreenOffMs, procState)) {
+                        Arrays.fill(timesInFreqScreenOffMs, 0);
                     }
                     final long procToken = proto.start(UidProto.Cpu.BY_PROCESS_STATE);
                     proto.write(UidProto.Cpu.ByProcessState.PROCESS_STATE, procState);
-                    for (int ic = 0; ic < timesMs.length; ++ic) {
+                    for (int ic = 0; ic < timesInFreqMs.length; ++ic) {
                         long cToken = proto.start(UidProto.Cpu.ByProcessState.BY_FREQUENCY);
                         proto.write(UidProto.Cpu.ByFrequency.FREQUENCY_INDEX, ic + 1);
                         proto.write(UidProto.Cpu.ByFrequency.TOTAL_DURATION_MS,
-                                timesMs[ic]);
+                                timesInFreqMs[ic]);
                         proto.write(UidProto.Cpu.ByFrequency.SCREEN_OFF_DURATION_MS,
-                                screenOffTimesMs[ic]);
+                                timesInFreqScreenOffMs[ic]);
                         proto.end(cToken);
                     }
                     proto.end(procToken);
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 743468a..35b9ccc 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1294,6 +1294,18 @@
     public static class Partition {
         /** The name identifying the system partition. */
         public static final String PARTITION_NAME_SYSTEM = "system";
+        /** @hide */
+        public static final String PARTITION_NAME_BOOTIMAGE = "bootimage";
+        /** @hide */
+        public static final String PARTITION_NAME_ODM = "odm";
+        /** @hide */
+        public static final String PARTITION_NAME_OEM = "oem";
+        /** @hide */
+        public static final String PARTITION_NAME_PRODUCT = "product";
+        /** @hide */
+        public static final String PARTITION_NAME_SYSTEM_EXT = "system_ext";
+        /** @hide */
+        public static final String PARTITION_NAME_VENDOR = "vendor";
 
         private final String mName;
         private final String mFingerprint;
@@ -1350,8 +1362,12 @@
         ArrayList<Partition> partitions = new ArrayList();
 
         String[] names = new String[] {
-            "bootimage", "odm", "product", "system_ext", Partition.PARTITION_NAME_SYSTEM,
-            "vendor"
+                Partition.PARTITION_NAME_BOOTIMAGE,
+                Partition.PARTITION_NAME_ODM,
+                Partition.PARTITION_NAME_PRODUCT,
+                Partition.PARTITION_NAME_SYSTEM_EXT,
+                Partition.PARTITION_NAME_SYSTEM,
+                Partition.PARTITION_NAME_VENDOR
         };
         for (String name : names) {
             String fingerprint = SystemProperties.get("ro." + name + ".build.fingerprint");
diff --git a/core/java/android/os/CombinedVibration.java b/core/java/android/os/CombinedVibration.java
index aff55af..5f2c113 100644
--- a/core/java/android/os/CombinedVibration.java
+++ b/core/java/android/os/CombinedVibration.java
@@ -110,6 +110,20 @@
     @TestApi
     public abstract long getDuration();
 
+    /**
+     * Returns true if this effect could represent a touch haptic feedback.
+     *
+     * <p>It is strongly recommended that an instance of {@link VibrationAttributes} is specified
+     * for each vibration, with the correct usage. When a vibration is played with usage UNKNOWN,
+     * then this method will be used to classify the most common use case and make sure they are
+     * covered by the user settings for "Touch feedback".
+     *
+     * @hide
+     */
+    public boolean isHapticFeedbackCandidate() {
+        return false;
+    }
+
     /** @hide */
     public abstract void validate();
 
@@ -314,6 +328,12 @@
 
         /** @hide */
         @Override
+        public boolean isHapticFeedbackCandidate() {
+            return mEffect.isHapticFeedbackCandidate();
+        }
+
+        /** @hide */
+        @Override
         public void validate() {
             mEffect.validate();
         }
@@ -431,6 +451,17 @@
 
         /** @hide */
         @Override
+        public boolean isHapticFeedbackCandidate() {
+            for (int i = 0; i < mEffects.size(); i++) {
+                if (!mEffects.valueAt(i).isHapticFeedbackCandidate()) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /** @hide */
+        @Override
         public void validate() {
             Preconditions.checkArgument(mEffects.size() > 0,
                     "There should be at least one effect set for a combined effect");
@@ -513,6 +544,9 @@
      */
     @TestApi
     public static final class Sequential extends CombinedVibration {
+        // If a vibration is playing more than 3 effects, it's probably not haptic feedback
+        private static final long MAX_HAPTIC_FEEDBACK_SEQUENCE_SIZE = 3;
+
         private final List<CombinedVibration> mEffects;
         private final List<Integer> mDelays;
 
@@ -575,6 +609,21 @@
 
         /** @hide */
         @Override
+        public boolean isHapticFeedbackCandidate() {
+            final int effectCount = mEffects.size();
+            if (effectCount > MAX_HAPTIC_FEEDBACK_SEQUENCE_SIZE) {
+                return false;
+            }
+            for (int i = 0; i < effectCount; i++) {
+                if (!mEffects.get(i).isHapticFeedbackCandidate()) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        /** @hide */
+        @Override
         public void validate() {
             Preconditions.checkArgument(mEffects.size() > 0,
                     "There should be at least one effect set for a combined effect");
diff --git a/core/java/android/os/ExternalVibration.java b/core/java/android/os/ExternalVibration.java
index 0686dd6..4e0995f 100644
--- a/core/java/android/os/ExternalVibration.java
+++ b/core/java/android/os/ExternalVibration.java
@@ -99,7 +99,7 @@
     }
 
     public VibrationAttributes getVibrationAttributes() {
-        return new VibrationAttributes.Builder(mAttrs, null).build();
+        return new VibrationAttributes.Builder(mAttrs).build();
     }
 
     /**
diff --git a/core/java/android/os/IStatsBootstrapAtomService.aidl b/core/java/android/os/IStatsBootstrapAtomService.aidl
new file mode 100644
index 0000000..9d1df67
--- /dev/null
+++ b/core/java/android/os/IStatsBootstrapAtomService.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2021, 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 android.os;
+
+import android.os.StatsBootstrapAtom;
+
+/**
+ * IBootstrapAtomService interface exposes an interface for processes that launch in the
+ * bootstrap namespace to push atoms to statsd.
+ *
+ * @hide
+ */
+oneway interface IStatsBootstrapAtomService {
+    /**
+     * Push an atom to StatsBootstrapAtomService, which will forward it to statsd.
+     *
+     * @param atom - parcelled representation of the atom to log.
+     *
+     * Errors are reported as service specific errors.
+     */
+    void reportBootstrapAtom(in StatsBootstrapAtom atom);
+}
\ No newline at end of file
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index b839706..3f42164 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -20,6 +20,7 @@
 import android.os.Bundle;
 import android.os.IUserRestrictionsListener;
 import android.os.PersistableBundle;
+import android.os.UserHandle;
 import android.os.UserManager;
 import android.content.pm.UserInfo;
 import android.content.IntentSender;
@@ -59,6 +60,8 @@
     List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying, boolean excludePreCreated);
     List<UserInfo> getProfiles(int userId, boolean enabledOnly);
     int[] getProfileIds(int userId, boolean enabledOnly);
+    boolean isUserTypeEnabled(in String userType);
+    boolean canAddMoreUsersOfType(in String userType);
     boolean canAddMoreProfilesToUser(in String userType, int userId, boolean allowedToRemoveOne);
     boolean canAddMoreManagedProfiles(int userId, boolean allowedToRemoveOne);
     UserInfo getProfileParent(int userId);
@@ -91,6 +94,9 @@
     boolean markGuestForDeletion(int userId);
     UserInfo findCurrentGuestUser();
     boolean isQuietModeEnabled(int userId);
+    UserHandle createUserWithAttributes(in String userName, in String userType, int flags,
+            in Bitmap userIcon,
+            in String accountName, in String accountType, in PersistableBundle accountOptions);
     void setSeedAccountData(int userId, in String accountName,
             in String accountType, in PersistableBundle accountOptions, boolean persist);
     String getSeedAccountName(int userId);
@@ -98,6 +104,7 @@
     PersistableBundle getSeedAccountOptions(int userId);
     void clearSeedAccountData(int userId);
     boolean someUserHasSeedAccount(in String accountName, in String accountType);
+    boolean someUserHasAccount(in String accountName, in String accountType);
     boolean isProfile(int userId);
     boolean isManagedProfile(int userId);
     boolean isCloneProfile(int userId);
diff --git a/core/java/android/os/NewUserRequest.java b/core/java/android/os/NewUserRequest.java
new file mode 100644
index 0000000..b0e1f91
--- /dev/null
+++ b/core/java/android/os/NewUserRequest.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2021 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 android.os;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.content.pm.UserInfo;
+import android.graphics.Bitmap;
+import android.text.TextUtils;
+
+/**
+ * Contains necessary information to create user using
+ * {@link UserManager#createUser(NewUserRequest)}.
+ *
+ * @hide
+ */
+@SystemApi
+@SuppressLint("PackageLayering")
+public final class NewUserRequest {
+    @Nullable
+    private final String mName;
+    private final boolean mAdmin;
+    private final boolean mEphemeral;
+    @NonNull
+    private final String mUserType;
+    private final Bitmap mUserIcon;
+    private final String mAccountName;
+    private final String mAccountType;
+    private final PersistableBundle mAccountOptions;
+
+    private NewUserRequest(Builder builder) {
+        mName = builder.mName;
+        mAdmin = builder.mAdmin;
+        mEphemeral = builder.mEphemeral;
+        mUserType = builder.mUserType;
+        mUserIcon = builder.mUserIcon;
+        mAccountName = builder.mAccountName;
+        mAccountType = builder.mAccountType;
+        mAccountOptions = builder.mAccountOptions;
+    }
+
+    /**
+     * Returns the name of the user.
+     */
+    @Nullable
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * Returns whether the user is ephemeral.
+     *
+     * <p> Ephemeral user will be removed after leaving the foreground.
+     */
+    public boolean isEphemeral() {
+        return mEphemeral;
+    }
+
+    /**
+     * Returns whether the user is an admin.
+     *
+     * <p> Admin user is with administrative privileges and such user can create and
+     * delete users.
+     */
+    public boolean isAdmin() {
+        return mAdmin;
+    }
+
+    /**
+     * Returns the calculated flags for user creation.
+     */
+    int getFlags() {
+        int flags = 0;
+        if (isAdmin()) flags |= UserInfo.FLAG_ADMIN;
+        if (isEphemeral()) flags |= UserInfo.FLAG_EPHEMERAL;
+        return flags;
+    }
+
+    /**
+     * Returns the user type.
+     *
+     * <p> Supported types are {@link UserManager.USER_TYPE_FULL_SECONDARY} and
+     * {@link USER_TYPE_FULL_GUEST}
+     */
+    @NonNull
+    public String getUserType() {
+        return mUserType;
+    }
+
+    /**
+     * Returns the user icon.
+     */
+    @Nullable
+    public Bitmap getUserIcon() {
+        return mUserIcon;
+    }
+
+    /**
+     * Returns the account name.
+     */
+    @Nullable
+    public String getAccountName() {
+        return mAccountName;
+    }
+
+    /**
+     * Returns the account type.
+     */
+    @Nullable
+    public String getAccountType() {
+        return mAccountType;
+    }
+
+    /**
+     * Returns the account options.
+     */
+    @SuppressLint("NullableCollection")
+    @Nullable
+    public PersistableBundle getAccountOptions() {
+        return mAccountOptions;
+    }
+
+    @Override
+    public String toString() {
+        return "NewUserRequest{"
+                + "mName='" + mName + '\''
+                + ", mAdmin=" + mAdmin
+                + ", mEphemeral=" + mEphemeral
+                + ", mUserType='" + mUserType + '\''
+                + ", mAccountName='" + mAccountName + '\''
+                + ", mAccountType='" + mAccountType + '\''
+                + ", mAccountOptions=" + mAccountOptions
+                + '}';
+    }
+
+    /**
+     * Builder for building {@link NewUserRequest}
+     */
+    @SuppressLint("PackageLayering")
+    public static final class Builder {
+
+        private String mName;
+        private boolean mAdmin;
+        private boolean mEphemeral;
+        private String mUserType = UserManager.USER_TYPE_FULL_SECONDARY;
+        private Bitmap mUserIcon;
+        private String mAccountName;
+        private String mAccountType;
+        private PersistableBundle mAccountOptions;
+
+        /**
+         * Sets user name.
+         *
+         * @return This object for method chaining.
+         */
+        @NonNull
+        public Builder setName(@Nullable String name) {
+            mName = name;
+            return this;
+        }
+
+        /**
+         * Sets user as admin.
+         *
+         * <p> Admin user is with administrative privileges and such user can create
+         * and delete users.
+         *
+         * @return This object for method chaining.
+         */
+        @NonNull
+        public Builder setAdmin() {
+            mAdmin = true;
+            return this;
+        }
+
+        /**
+         * Sets user as ephemeral.
+         *
+         * <p> Ephemeral user will be removed after leaving the foreground.
+         *
+         * @return This object for method chaining.
+         */
+        @NonNull
+        public Builder setEphemeral() {
+            mEphemeral = true;
+            return this;
+        }
+
+        /**
+         * Sets user type.
+         * <p>
+         * Supported types are {@link UserManager.USER_TYPE_FULL_SECONDARY} and
+         * {@link UserManager.USER_TYPE_FULL_GUEST}. Default value is
+         * {@link UserManager.USER_TYPE_FULL_SECONDARY}.
+         *
+         * @return This object for method chaining.
+         */
+        @NonNull
+        public Builder setUserType(@NonNull String type) {
+            mUserType = type;
+            return this;
+        }
+
+        /**
+         * Sets user icon.
+         *
+         * @return This object for method chaining.
+         */
+        @NonNull
+        public Builder setUserIcon(@Nullable Bitmap userIcon) {
+            mUserIcon = userIcon;
+            return this;
+        }
+
+        /**
+         * Sets account name that will be used by the setup wizard to initialize the user.
+         *
+         * @see android.accounts.Account
+         * @return This object for method chaining.
+         */
+        @NonNull
+        public Builder setAccountName(@Nullable String accountName) {
+            mAccountName = accountName;
+            return this;
+        }
+
+        /**
+         * Sets account type for the account to be created. This is required if the account name
+         * is not null. This will be used by the setup wizard to initialize the user.
+         *
+         * @see android.accounts.Account
+         * @return This object for method chaining.
+         */
+        @NonNull
+        public Builder setAccountType(@Nullable String accountType) {
+            mAccountType = accountType;
+            return this;
+        }
+
+        /**
+         * Sets account options that can contain account-specific extra information
+         * to be used by setup wizard to initialize the account for the user.
+         *
+         * @return This object for method chaining.
+         */
+        @NonNull
+        public Builder setAccountOptions(@Nullable PersistableBundle accountOptions) {
+            mAccountOptions = accountOptions;
+            return this;
+        }
+
+        /**
+         * Builds {@link NewUserRequest}
+         *
+         * @throws IllegalStateException if builder is configured with incompatible properties and
+         * it is not possible to create such user. For example - a guest admin user.
+         */
+        @NonNull
+        public NewUserRequest build() {
+            checkIfPropertiesAreCompatible();
+            return new NewUserRequest(this);
+        }
+
+        private void checkIfPropertiesAreCompatible() {
+            // Conditions which can't be true simultaneously
+            // A guest user can't be admin user
+            if (mAdmin && mUserType == UserManager.USER_TYPE_FULL_GUEST) {
+                throw new IllegalStateException("A guest user can't be admin.");
+            }
+
+            // check for only supported user types
+            if (mUserType != UserManager.USER_TYPE_FULL_SECONDARY
+                    && mUserType != UserManager.USER_TYPE_FULL_GUEST) {
+                throw new IllegalStateException("Unsupported user type: " + mUserType);
+            }
+
+            if (TextUtils.isEmpty(mAccountName) != TextUtils.isEmpty(mAccountType)) {
+                throw new IllegalStateException(
+                        "Account name and account type should be provided together.");
+            }
+        }
+    }
+}
diff --git a/core/java/android/os/NewUserResponse.java b/core/java/android/os/NewUserResponse.java
new file mode 100644
index 0000000..3869559
--- /dev/null
+++ b/core/java/android/os/NewUserResponse.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 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 android.os;
+
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+
+/**
+ * Contains the response of the call {@link UserManager#createUser(NewUserRequest)}.
+ *
+ * @hide
+ */
+@SystemApi
+public final class NewUserResponse {
+
+    private final @Nullable UserHandle mUser;
+    private final @UserManager.UserOperationResult int mOperationResult;
+
+    NewUserResponse(@Nullable UserHandle user,
+            @UserManager.UserOperationResult int operationResult) {
+        mUser = user;
+        mOperationResult = operationResult;
+    }
+
+    /**
+     * Is user creation successful?
+     */
+    public boolean isSuccessful() {
+        return mUser != null;
+    }
+
+    // TODO(b/199446283): If UserHandle.NULL is systemAPI, that can be returned here instead of null
+    /**
+     * Gets the created user handle.
+     */
+    public @Nullable UserHandle getUser() {
+        return mUser;
+    }
+
+    /**
+     * Gets operation results.
+     */
+    public @UserManager.UserOperationResult int getOperationResult() {
+        return mOperationResult;
+    }
+}
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 92861fb..1e424d1 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -1,18 +1,6 @@
 # Haptics
-per-file CombinedVibrationEffect.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file CombinedVibrationEffect.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file ExternalVibration.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file ExternalVibration.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file IExternalVibrationController.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file IExternalVibratorService.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file IVibratorManagerService.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file NullVibrator.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file SystemVibrator.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file SystemVibratorManager.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file VibrationEffect.aidl = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file VibrationEffect.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file Vibrator.java = file:/services/core/java/com/android/server/vibrator/OWNERS
-per-file VibratorManager.java = file:/services/core/java/com/android/server/vibrator/OWNERS
+per-file *Vibration* = file:/services/core/java/com/android/server/vibrator/OWNERS
+per-file *Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
 
 # PowerManager
 per-file IPowerManager.aidl = michaelwr@google.com, santoscordon@google.com
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 09e5a8f..7bdb6b9 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -2990,7 +2990,12 @@
      * Please use {@link #readBundle(ClassLoader)} instead (whose data must have
      * been written with {@link #writeBundle}.  Read into an existing Map object
      * from the parcel at the current dataPosition().
+     *
+     * @deprecated Consider using {@link #readBundle(ClassLoader)} as stated above, in case this
+     *      method is still preferred use the type-safer version {@link #readMap(Map, ClassLoader,
+     *      Class, Class)} starting from Android {@link Build.VERSION_CODES#TIRAMISU}.
      */
+    @Deprecated
     public final void readMap(@NonNull Map outVal, @Nullable ClassLoader loader) {
         int n = readInt();
         readMapInternal(outVal, n, loader, /* clazzKey */ null, /* clazzValue */ null);
@@ -3016,7 +3021,14 @@
      * Read into an existing List object from the parcel at the current
      * dataPosition(), using the given class loader to load any enclosed
      * Parcelables.  If it is null, the default class loader is used.
+     *
+     * @deprecated Use the type-safer version {@link #readList(List, ClassLoader, Class)} starting
+     *      from Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the format to
+     *      use {@link #readTypedList(List, Parcelable.Creator)} if possible (eg. if the items'
+     *      class is final) since this is also more performant. Note that changing to the latter
+     *      also requires changing the writes.
      */
+    @Deprecated
     public final void readList(@NonNull List outVal, @Nullable ClassLoader loader) {
         int N = readInt();
         readListInternal(outVal, N, loader, /* clazz */ null);
@@ -3043,10 +3055,14 @@
      * object from the parcel at the current dataPosition(), using the given
      * class loader to load any enclosed Parcelables.  Returns null if
      * the previously written map object was null.
+     *
+     * @deprecated Consider using {@link #readBundle(ClassLoader)} as stated above, in case this
+     *      method is still preferred use the type-safer version {@link #readHashMap(ClassLoader,
+     *      Class, Class)} starting from Android {@link Build.VERSION_CODES#TIRAMISU}.
      */
+    @Deprecated
     @Nullable
-    public final HashMap readHashMap(@Nullable ClassLoader loader)
-    {
+    public HashMap readHashMap(@Nullable ClassLoader loader) {
         int n = readInt();
         if (n < 0) {
             return null;
@@ -3247,7 +3263,14 @@
      * dataPosition().  Returns null if the previously written list object was
      * null.  The given class loader will be used to load any enclosed
      * Parcelables.
+     *
+     * @deprecated Use the type-safer version {@link #readArrayList(ClassLoader, Class)} starting
+     *      from Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the format to
+     *      use {@link #createTypedArrayList(Parcelable.Creator)} if possible (eg. if the items'
+     *      class is final) since this is also more performant. Note that changing to the latter
+     *      also requires changing the writes.
      */
+    @Deprecated
     @Nullable
     public ArrayList readArrayList(@Nullable ClassLoader loader) {
         return readArrayListInternal(loader, /* clazz */ null);
@@ -3274,7 +3297,14 @@
      * dataPosition().  Returns null if the previously written array was
      * null.  The given class loader will be used to load any enclosed
      * Parcelables.
+     *
+     * @deprecated Use the type-safer version {@link #readArray(ClassLoader, Class)} starting from
+     *      Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the format to use
+     *      {@link #createTypedArray(Parcelable.Creator)} if possible (eg. if the items' class is
+     *      final) since this is also more performant. Note that changing to the latter also
+     *      requires changing the writes.
      */
+    @Deprecated
     @Nullable
     public Object[] readArray(@Nullable ClassLoader loader) {
         return readArrayInternal(loader, /* clazz */ null);
@@ -3300,7 +3330,14 @@
      * dataPosition().  Returns null if the previously written list object was
      * null.  The given class loader will be used to load any enclosed
      * Parcelables.
+     *
+     * @deprecated Use the type-safer version {@link #readSparseArray(ClassLoader, Class)} starting
+     *      from Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the format to
+     *      use {@link #createTypedSparseArray(Parcelable.Creator)} if possible (eg. if the items'
+     *      class is final) since this is also more performant. Note that changing to the latter
+     *      also requires changing the writes.
      */
+    @Deprecated
     @Nullable
     public <T> SparseArray<T> readSparseArray(@Nullable ClassLoader loader) {
         return readSparseArrayInternal(loader, /* clazz */ null);
@@ -4107,7 +4144,13 @@
      * object has been written.
      * @throws BadParcelableException Throws BadParcelableException if there
      * was an error trying to instantiate the Parcelable.
+     *
+     * @deprecated Use the type-safer version {@link #readParcelable(ClassLoader, Class)} starting
+     *      from Android {@link Build.VERSION_CODES#TIRAMISU}. Also consider changing the format to
+     *      use {@link Parcelable.Creator#createFromParcel(Parcel)} if possible since this is also
+     *      more performant. Note that changing to the latter also requires changing the writes.
      */
+    @Deprecated
     @Nullable
     public final <T extends Parcelable> T readParcelable(@Nullable ClassLoader loader) {
         return readParcelableInternal(loader, /* clazz */ null);
@@ -4176,7 +4219,11 @@
      * read the {@link Parcelable.Creator}.
      *
      * @see #writeParcelableCreator
+     *
+     * @deprecated Use the type-safer version {@link #readParcelableCreator(ClassLoader, Class)}
+     *       starting from Android {@link Build.VERSION_CODES#TIRAMISU}.
      */
+    @Deprecated
     @Nullable
     public final Parcelable.Creator<?> readParcelableCreator(@Nullable ClassLoader loader) {
         return readParcelableCreatorInternal(loader, /* clazz */ null);
@@ -4337,7 +4384,11 @@
      * Read and return a new Serializable object from the parcel.
      * @return the Serializable object, or null if the Serializable name
      * wasn't found in the parcel.
+     *
+     * @deprecated Use the type-safer version {@link #readSerializable(ClassLoader, Class)} starting
+     *       from Android {@link Build.VERSION_CODES#TIRAMISU}.
      */
+    @Deprecated
     @Nullable
     public Serializable readSerializable() {
         return readSerializableInternal(/* loader */ null, /* clazz */ null);
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 753f349..74fffd0 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -440,9 +440,15 @@
     public static final int GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF = 12;
 
     /**
+     * Go to sleep reason code: A foldable device has been folded.
      * @hide
      */
-    public static final int GO_TO_SLEEP_REASON_MAX = GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF;
+    public static final int GO_TO_SLEEP_REASON_DEVICE_FOLD = 13;
+
+    /**
+     * @hide
+     */
+    public static final int GO_TO_SLEEP_REASON_MAX =  GO_TO_SLEEP_REASON_DEVICE_FOLD;
 
     /**
      * @hide
@@ -461,6 +467,7 @@
             case GO_TO_SLEEP_REASON_INATTENTIVE: return "inattentive";
             case GO_TO_SLEEP_REASON_DISPLAY_GROUP_REMOVED: return "display_group_removed";
             case GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF: return "display_groups_turned_off";
+            case GO_TO_SLEEP_REASON_DEVICE_FOLD: return "device_folded";
             default: return Integer.toString(sleepReason);
         }
     }
@@ -568,7 +575,8 @@
             GO_TO_SLEEP_REASON_ACCESSIBILITY,
             GO_TO_SLEEP_REASON_FORCE_SUSPEND,
             GO_TO_SLEEP_REASON_INATTENTIVE,
-            GO_TO_SLEEP_REASON_QUIESCENT
+            GO_TO_SLEEP_REASON_QUIESCENT,
+            GO_TO_SLEEP_REASON_DEVICE_FOLD
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface GoToSleepReason{}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 9f37c48..742a542 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -18,11 +18,14 @@
 
 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
 
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
+import android.annotation.UptimeMillisLong;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.os.Build.VERSION_CODES;
 import android.system.ErrnoException;
 import android.system.Os;
 import android.system.OsConstants;
@@ -553,9 +556,26 @@
     public static final int SIGNAL_KILL = 9;
     public static final int SIGNAL_USR1 = 10;
 
+    /**
+     * When the process started and ActivityThread.handleBindApplication() was executed.
+     */
     private static long sStartElapsedRealtime;
+
+    /**
+     * When the process started and ActivityThread.handleBindApplication() was executed.
+     */
     private static long sStartUptimeMillis;
 
+    /**
+     * When the activity manager was about to ask zygote to fork.
+     */
+    private static long sStartRequestedElapsedRealtime;
+
+    /**
+     * When the activity manager was about to ask zygote to fork.
+     */
+    private static long sStartRequestedUptimeMillis;
+
     private static final int PIDFD_UNKNOWN = 0;
     private static final int PIDFD_SUPPORTED = 1;
     private static final int PIDFD_UNSUPPORTED = 2;
@@ -605,6 +625,12 @@
      */
     public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();
 
+
+    /**
+     * The process name set via {@link #setArgV0(String)}.
+     */
+    private static String sArgV0;
+
     /**
      * Start a new process.
      * 
@@ -716,23 +742,56 @@
     public static final native long getElapsedCpuTime();
 
     /**
-     * Return the {@link SystemClock#elapsedRealtime()} at which this process was started.
+     * Return the {@link SystemClock#elapsedRealtime()} at which this process was started,
+     * but before any of the application code was executed.
      */
-    public static final long getStartElapsedRealtime() {
+    @ElapsedRealtimeLong
+    public static long getStartElapsedRealtime() {
         return sStartElapsedRealtime;
     }
 
     /**
-     * Return the {@link SystemClock#uptimeMillis()} at which this process was started.
+     * Return the {@link SystemClock#uptimeMillis()} at which this process was started,
+     * but before any of the application code was executed.
      */
-    public static final long getStartUptimeMillis() {
+    @UptimeMillisLong
+    public static long getStartUptimeMillis() {
         return sStartUptimeMillis;
     }
 
+    /**
+     * Return the {@link SystemClock#elapsedRealtime()} at which the system was about to
+     * start this process. i.e. before a zygote fork.
+     *
+     * <p>More precisely, the system may start app processes before there's a start request,
+     * in order to reduce the process start up latency, in which case this is set when the system
+     * decides to "specialize" the process into a requested app.
+     */
+    @ElapsedRealtimeLong
+    public static long getStartRequestedElapsedRealtime() {
+        return sStartRequestedElapsedRealtime;
+    }
+
+    /**
+     * Return the {@link SystemClock#uptimeMillis()} at which the system was about to
+     * start this process. i.e. before a zygote fork.
+     *
+     * <p>More precisely, the system may start app processes before there's a start request,
+     * in order to reduce the process start up latency, in which case this is set when the system
+     * decides to "specialize" the process into a requested app.
+     */
+    @UptimeMillisLong
+    public static long getStartRequestedUptimeMillis() {
+        return sStartRequestedUptimeMillis;
+    }
+
     /** @hide */
-    public static final void setStartTimes(long elapsedRealtime, long uptimeMillis) {
+    public static final void setStartTimes(long elapsedRealtime, long uptimeMillis,
+            long startRequestedElapsedRealtime, long startRequestedUptime) {
         sStartElapsedRealtime = elapsedRealtime;
         sStartUptimeMillis = uptimeMillis;
+        sStartRequestedElapsedRealtime = startRequestedElapsedRealtime;
+        sStartRequestedUptimeMillis = startRequestedUptime;
     }
 
     /**
@@ -1135,8 +1194,27 @@
      * 
      * {@hide}
      */
-    @UnsupportedAppUsage
-    public static final native void setArgV0(String text);
+    @UnsupportedAppUsage(maxTargetSdk = VERSION_CODES.S, publicAlternatives = "Do not try to "
+            + "change the process name. (If you must, you could use {@code pthread_setname_np(3)}, "
+            + "but this could confuse the system)")
+    public static void setArgV0(@NonNull String text) {
+        sArgV0 = text;
+        setArgV0Native(text);
+    }
+
+    private static native void setArgV0Native(String text);
+
+    /**
+     * Return the name of this process. By default, the process name is the same as the app's
+     * package name, but this can be changed using {@code android:process}.
+     */
+    @NonNull
+    public static String myProcessName() {
+        // Note this could be different from the actual process name if someone changes the
+        // process name using native code (using pthread_setname_np()). But sArgV0
+        // is the name that the system thinks this process has.
+        return sArgV0;
+    }
 
     /**
      * Kill the process with the given PID.
diff --git a/core/java/android/os/ServiceManager.java b/core/java/android/os/ServiceManager.java
index 4e8418b..ba5ed43 100644
--- a/core/java/android/os/ServiceManager.java
+++ b/core/java/android/os/ServiceManager.java
@@ -298,6 +298,17 @@
     }
 
     /**
+     * Register callback for service registration notifications.
+     *
+     * @throws RemoteException for underlying error.
+     * @hide
+     */
+    public static void registerForNotifications(
+            @NonNull String name, @NonNull IServiceCallback callback) throws RemoteException {
+        getIServiceManager().registerForNotifications(name, callback);
+    }
+
+    /**
      * Return a list of all currently running services.
      * @return an array of all currently running services, or <code>null</code> in
      * case of an exception
diff --git a/core/java/android/os/ServiceManagerNative.java b/core/java/android/os/ServiceManagerNative.java
index 3739040..2dcf674 100644
--- a/core/java/android/os/ServiceManagerNative.java
+++ b/core/java/android/os/ServiceManagerNative.java
@@ -78,7 +78,7 @@
 
     public void registerForNotifications(String name, IServiceCallback cb)
             throws RemoteException {
-        throw new RemoteException();
+        mServiceManager.registerForNotifications(name, cb);
     }
 
     public void unregisterForNotifications(String name, IServiceCallback cb)
diff --git a/core/java/android/os/StatsBootstrapAtom.aidl b/core/java/android/os/StatsBootstrapAtom.aidl
new file mode 100644
index 0000000..47500af
--- /dev/null
+++ b/core/java/android/os/StatsBootstrapAtom.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021, 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 android.os;
+
+import android.os.StatsBootstrapAtomValue;
+
+/*
+ * Generic encapsulation of an atom for bootstrap processes to log.
+ *
+ * @hide
+ */
+parcelable StatsBootstrapAtom {
+    /*
+     * Atom ID. Must be between 1 - 10,000.
+     */
+    int atomId;
+    /*
+     * Vector of fields in the order of the atom definition.
+     */
+    StatsBootstrapAtomValue[] values;
+ }
\ No newline at end of file
diff --git a/packages/overlays/OneHandedModeGesturalOverlay/res/values/dimens.xml b/core/java/android/os/StatsBootstrapAtomValue.aidl
similarity index 65%
rename from packages/overlays/OneHandedModeGesturalOverlay/res/values/dimens.xml
rename to core/java/android/os/StatsBootstrapAtomValue.aidl
index 3986119..a90dfa4 100644
--- a/packages/overlays/OneHandedModeGesturalOverlay/res/values/dimens.xml
+++ b/core/java/android/os/StatsBootstrapAtomValue.aidl
@@ -1,7 +1,5 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/**
- * Copyright (c) 2020, The Android Open Source Project
+/*
+ * Copyright 2021, 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.
@@ -15,8 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
--->
-<resources>
-    <!-- The height of the bottom navigation gesture area. -->
-    <dimen name="navigation_bar_gesture_larger_height">80dp</dimen>
-</resources>
+package android.os;
+/*
+ * Supported field types.
+ *
+ * @hide
+ */
+union StatsBootstrapAtomValue {
+    boolean boolValue;
+    int intValue;
+    long longValue;
+    float floatValue;
+    String stringValue;
+    byte[] bytesValue;
+}
\ No newline at end of file
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index a243453..d0d6cb7 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
-import android.media.AudioAttributes;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.SparseArray;
@@ -180,14 +179,13 @@
 
     @Override
     public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect,
-            AudioAttributes attributes) {
+            VibrationAttributes attrs) {
         if (mVibratorManager == null) {
             Log.w(TAG, "Failed to set always-on effect; no vibrator manager.");
             return false;
         }
-        VibrationAttributes attr = new VibrationAttributes.Builder(attributes, effect).build();
         CombinedVibration combinedEffect = CombinedVibration.createParallel(effect);
-        return mVibratorManager.setAlwaysOnEffect(uid, opPkg, alwaysOnId, combinedEffect, attr);
+        return mVibratorManager.setAlwaysOnEffect(uid, opPkg, alwaysOnId, combinedEffect, attrs);
     }
 
     @Override
diff --git a/core/java/android/os/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java
index 0416556..c690df2 100644
--- a/core/java/android/os/SystemVibratorManager.java
+++ b/core/java/android/os/SystemVibratorManager.java
@@ -20,7 +20,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.media.AudioAttributes;
 import android.util.ArrayMap;
 import android.util.Log;
 import android.util.SparseArray;
@@ -210,14 +209,12 @@
 
         @Override
         public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
-                @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes) {
-            VibrationAttributes attr = new VibrationAttributes.Builder(
-                    attributes, effect).build();
+                @Nullable VibrationEffect effect, @Nullable VibrationAttributes attrs) {
             CombinedVibration combined = CombinedVibration.startParallel()
                     .addVibrator(mVibratorInfo.getId(), effect)
                     .combine();
             return SystemVibratorManager.this.setAlwaysOnEffect(uid, opPkg, alwaysOnId, combined,
-                    attr);
+                    attrs);
         }
 
         @Override
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 14d7e82..bc6dbd8 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -70,6 +70,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 
 /**
@@ -118,6 +119,7 @@
      * User type representing a guest user that may be transient.
      * @hide
      */
+    @SystemApi
     public static final String USER_TYPE_FULL_GUEST = "android.os.usertype.full.GUEST";
 
     /**
@@ -306,6 +308,25 @@
     public static final String DISALLOW_WIFI_TETHERING = "no_wifi_tethering";
 
     /**
+     * Specifies if users are disallowed from sharing Wi-Fi for admin configured networks.
+     *
+     * <p>Device owner and profile owner can set this restriction.
+     * When it is set by any of these owners, it prevents all users from
+     * sharing Wi-Fi for networks configured by these owners.
+     * Other networks not configured by these owners are not affected.
+     *
+     * <p>The default value is <code>false</code>.
+     *
+     * <p>Key for user restrictions.
+     * <p>Type: Boolean
+     * @see DevicePolicyManager#addUserRestriction(ComponentName, String)
+     * @see DevicePolicyManager#clearUserRestriction(ComponentName, String)
+     * @see #getUserRestrictions()
+     */
+    public static final String DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI =
+            "no_sharing_admin_configured_wifi";
+
+    /**
      * Specifies if a user is disallowed from changing the device
      * language. The default value is <code>false</code>.
      *
@@ -1476,6 +1497,9 @@
             DISALLOW_CAMERA_TOGGLE,
             KEY_RESTRICTIONS_PENDING,
             DISALLOW_BIOMETRIC,
+            DISALLOW_CHANGE_WIFI_STATE,
+            DISALLOW_WIFI_TETHERING,
+            DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface UserRestrictionKey {}
@@ -1660,6 +1684,14 @@
     public static final int USER_OPERATION_ERROR_MAX_USERS = 6;
 
     /**
+     * Indicates user operation failed because a user with that account already exists.
+     *
+     * @hide
+     */
+    @SystemApi
+    public static final int USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS = 7;
+
+    /**
      * Result returned from various user operations.
      *
      * @hide
@@ -1672,7 +1704,8 @@
             USER_OPERATION_ERROR_MAX_RUNNING_USERS,
             USER_OPERATION_ERROR_CURRENT_USER,
             USER_OPERATION_ERROR_LOW_STORAGE,
-            USER_OPERATION_ERROR_MAX_USERS
+            USER_OPERATION_ERROR_MAX_USERS,
+            USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS
     })
     public @interface UserOperationResult {}
 
@@ -3148,6 +3181,37 @@
     }
 
     /**
+     * Creates a user with the specified {@link NewUserRequest}.
+     *
+     * @param newUserRequest specify the user information
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+            Manifest.permission.CREATE_USERS})
+    public @NonNull NewUserResponse createUser(@NonNull NewUserRequest newUserRequest) {
+        try {
+            final UserHandle userHandle = mService.createUserWithAttributes(
+                    newUserRequest.getName(),
+                    newUserRequest.getUserType(),
+                    newUserRequest.getFlags(),
+                    newUserRequest.getUserIcon(),
+                    newUserRequest.getAccountName(),
+                    newUserRequest.getAccountType(),
+                    newUserRequest.getAccountOptions());
+
+            return new NewUserResponse(userHandle, USER_OPERATION_SUCCESS);
+
+        } catch (ServiceSpecificException e) {
+            Log.w(TAG, "Exception while creating user " + newUserRequest, e);
+            return new NewUserResponse(null, e.errorCode);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Pre-creates a user of the specified type. Default user restrictions will be applied.
      *
      * <p>This method can be used by OEMs to "warm" up the user creation by pre-creating some users
@@ -3812,13 +3876,19 @@
     }
 
     /**
-     * Checks whether it's possible to add more users. Caller must hold the MANAGE_USERS
-     * permission.
+     * Checks whether it's possible to add more users.
      *
      * @return true if more users can be added, false if limit has been reached.
+     *
+     * @deprecated use {@link #canAddMoreUsers(String)} instead.
+     *
      * @hide
      */
-    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+    @Deprecated
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
     public boolean canAddMoreUsers() {
         // TODO(b/142482943): UMS has different logic, excluding Demo and Profile from counting. Why
         //                    not here? The logic is inconsistent. See UMS.canAddMoreManagedProfiles
@@ -3835,6 +3905,25 @@
     }
 
     /**
+     * Checks whether it is possible to add more users of the given user type.
+     *
+     * @param userType the type of user, such as {@link UserManager#USER_TYPE_FULL_SECONDARY}.
+     * @return true if more users of the given type can be added, otherwise false.
+     * @hide
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
+    public boolean canAddMoreUsers(@NonNull String userType) {
+        try {
+            return canAddMoreUsers() && mService.canAddMoreUsersOfType(userType);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Checks whether it's possible to add more managed profiles. Caller must hold the MANAGE_USERS
      * permission.
      * if allowedToRemoveOne is true and if the user already has a managed profile, then return if
@@ -3869,6 +3958,25 @@
     }
 
     /**
+     * Checks whether this device supports users of the given user type.
+     *
+     * @param userType the type of user, such as {@link UserManager#USER_TYPE_FULL_SECONDARY}.
+     * @return true if the creation of users of the given user type is enabled on this device.
+     * @hide
+     */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.MANAGE_USERS,
+            android.Manifest.permission.CREATE_USERS
+    })
+    public boolean isUserTypeEnabled(@NonNull String userType) {
+        try {
+            return mService.isUserTypeEnabled(userType);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Returns list of the profiles of userId including userId itself.
      * Note that this returns both enabled and not enabled profiles. See
      * {@link #getEnabledProfiles(int)} if you need only the enabled ones.
@@ -4879,12 +4987,12 @@
     }
 
     /**
-     * @hide
      * Checks if any uninitialized user has the specific seed account name and type.
      *
      * @param accountName The account name to check for
      * @param accountType The account type of the account to check for
      * @return whether the seed account was found
+     * @hide
      */
     @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean someUserHasSeedAccount(String accountName, String accountType) {
@@ -4896,6 +5004,29 @@
     }
 
     /**
+     * Checks if any initialized or uninitialized user has the specific account name and type.
+     *
+     * @param accountName The account name to check for
+     * @param accountType The account type of the account to check for
+     * @return whether the account was found
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+            Manifest.permission.CREATE_USERS})
+    public boolean someUserHasAccount(
+            @NonNull String accountName, @NonNull String accountType) {
+        Objects.requireNonNull(accountName, "accountName must not be null");
+        Objects.requireNonNull(accountType, "accountType must not be null");
+
+        try {
+            return mService.someUserHasAccount(accountName, accountType);
+        } catch (RemoteException re) {
+            throw re.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * @hide
      * User that enforces a restriction.
      *
diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java
index 9f799f9e..9612ca6 100644
--- a/core/java/android/os/VibrationAttributes.java
+++ b/core/java/android/os/VibrationAttributes.java
@@ -21,9 +21,6 @@
 import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.media.AudioAttributes;
-import android.os.vibrator.PrebakedSegment;
-import android.os.vibrator.VibrationEffectSegment;
-import android.util.Slog;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -81,6 +78,11 @@
      * actions, such as emulation of physical effects, and texting feedback vibration.
      */
     public static final int USAGE_CLASS_FEEDBACK = 0x2;
+    /**
+     * Vibration usage class value to use when the vibration is part of media, such as music, movie,
+     * soundtrack, game or animations.
+     */
+    public static final int USAGE_CLASS_MEDIA = 0x3;
 
     /**
      * Mask for vibration usage class value.
@@ -121,6 +123,15 @@
      * such as a fingerprint sensor.
      */
     public static final int USAGE_HARDWARE_FEEDBACK = 0x30 | USAGE_CLASS_FEEDBACK;
+    /**
+     * Usage value to use for accessibility vibrations, such as with a screen reader.
+     */
+    public static final int USAGE_ACCESSIBILITY = 0x40 | USAGE_CLASS_FEEDBACK;
+    /**
+     * Usage value to use for media vibrations, such as music, movie, soundtrack, animations, games,
+     * or any interactive media that isn't for touch feedback specifically.
+     */
+    public static final int USAGE_MEDIA = 0x10 | USAGE_CLASS_MEDIA;
 
     /**
      * @hide
@@ -142,8 +153,10 @@
      */
     public static final int FLAG_ALL_SUPPORTED = FLAG_BYPASS_INTERRUPTION_POLICY;
 
-    // If a vibration is playing for longer than 5s, it's probably not haptic feedback
-    private static final long MAX_HAPTIC_FEEDBACK_DURATION = 5000;
+    /** Creates a new {@link VibrationAttributes} instance with given usage. */
+    public static @NonNull VibrationAttributes createForUsage(int usage) {
+        return new VibrationAttributes.Builder().setUsage(usage).build();
+    }
 
     private final int mUsage;
     private final int mFlags;
@@ -203,13 +216,17 @@
             case USAGE_NOTIFICATION:
                 return AudioAttributes.USAGE_NOTIFICATION;
             case USAGE_COMMUNICATION_REQUEST:
-                return AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST;
+                return AudioAttributes.USAGE_VOICE_COMMUNICATION;
             case USAGE_RINGTONE:
                 return AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
             case USAGE_TOUCH:
                 return AudioAttributes.USAGE_ASSISTANCE_SONIFICATION;
             case USAGE_ALARM:
                 return AudioAttributes.USAGE_ALARM;
+            case USAGE_ACCESSIBILITY:
+                return AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY;
+            case USAGE_MEDIA:
+                return AudioAttributes.USAGE_MEDIA;
             default:
                 return AudioAttributes.USAGE_UNKNOWN;
         }
@@ -281,12 +298,16 @@
                 return "UNKNOWN";
             case USAGE_ALARM:
                 return "ALARM";
+            case USAGE_ACCESSIBILITY:
+                return "ACCESSIBILITY";
             case USAGE_RINGTONE:
                 return "RINGTONE";
             case USAGE_NOTIFICATION:
                 return "NOTIFICATION";
             case USAGE_COMMUNICATION_REQUEST:
                 return "COMMUNICATION_REQUEST";
+            case USAGE_MEDIA:
+                return "MEDIA";
             case USAGE_TOUCH:
                 return "TOUCH";
             case USAGE_PHYSICAL_EMULATION:
@@ -326,54 +347,10 @@
 
         /**
          * Constructs a new Builder from AudioAttributes.
-         * @hide
          */
-        @TestApi
-        public Builder(@NonNull AudioAttributes audio, @Nullable VibrationEffect effect) {
+        public Builder(@NonNull AudioAttributes audio) {
             setUsage(audio);
             setFlags(audio);
-            applyHapticFeedbackHeuristics(effect);
-        }
-
-        private void applyHapticFeedbackHeuristics(@Nullable VibrationEffect effect) {
-            if (effect != null) {
-                PrebakedSegment prebaked = extractPrebakedSegment(effect);
-                if (mUsage == USAGE_UNKNOWN && prebaked != null) {
-                    switch (prebaked.getEffectId()) {
-                        case VibrationEffect.EFFECT_CLICK:
-                        case VibrationEffect.EFFECT_DOUBLE_CLICK:
-                        case VibrationEffect.EFFECT_HEAVY_CLICK:
-                        case VibrationEffect.EFFECT_TEXTURE_TICK:
-                        case VibrationEffect.EFFECT_TICK:
-                        case VibrationEffect.EFFECT_POP:
-                        case VibrationEffect.EFFECT_THUD:
-                            mUsage = USAGE_TOUCH;
-                            break;
-                        default:
-                            Slog.w(TAG, "Unknown prebaked vibration effect, assuming it isn't "
-                                    + "haptic feedback");
-                    }
-                }
-                final long duration = effect.getDuration();
-                if (mUsage == USAGE_UNKNOWN && duration >= 0
-                        && duration < MAX_HAPTIC_FEEDBACK_DURATION) {
-                    mUsage = USAGE_TOUCH;
-                }
-            }
-        }
-
-        @Nullable
-        private PrebakedSegment extractPrebakedSegment(VibrationEffect effect) {
-            if (effect instanceof VibrationEffect.Composed) {
-                VibrationEffect.Composed composed = (VibrationEffect.Composed) effect;
-                if (composed.getSegments().size() == 1) {
-                    VibrationEffectSegment segment = composed.getSegments().get(0);
-                    if (segment instanceof PrebakedSegment) {
-                        return (PrebakedSegment) segment;
-                    }
-                }
-            }
-            return null;
         }
 
         private void setUsage(@NonNull AudioAttributes audio) {
@@ -383,21 +360,31 @@
                 case AudioAttributes.USAGE_NOTIFICATION_EVENT:
                 case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED:
                 case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT:
+                case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
                     mUsage = USAGE_NOTIFICATION;
                     break;
-                case AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST:
-                case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY:
+                case AudioAttributes.USAGE_VOICE_COMMUNICATION:
+                case AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING:
+                case AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE:
+                case AudioAttributes.USAGE_ASSISTANT:
                     mUsage = USAGE_COMMUNICATION_REQUEST;
                     break;
                 case AudioAttributes.USAGE_NOTIFICATION_RINGTONE:
                     mUsage = USAGE_RINGTONE;
                     break;
+                case AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY:
+                    mUsage = USAGE_ACCESSIBILITY;
+                    break;
                 case AudioAttributes.USAGE_ASSISTANCE_SONIFICATION:
                     mUsage = USAGE_TOUCH;
                     break;
                 case AudioAttributes.USAGE_ALARM:
                     mUsage = USAGE_ALARM;
                     break;
+                case AudioAttributes.USAGE_MEDIA:
+                case AudioAttributes.USAGE_GAME:
+                    mUsage = USAGE_MEDIA;
+                    break;
                 default:
                     mUsage = USAGE_UNKNOWN;
             }
@@ -428,6 +415,8 @@
          * {@link VibrationAttributes#USAGE_TOUCH},
          * {@link VibrationAttributes#USAGE_PHYSICAL_EMULATION},
          * {@link VibrationAttributes#USAGE_HARDWARE_FEEDBACK}.
+         * {@link VibrationAttributes#USAGE_ACCESSIBILITY}.
+         * {@link VibrationAttributes#USAGE_MEDIA}.
          * @return the same Builder instance.
          */
         public @NonNull Builder setUsage(int usage) {
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index a0cbbfe..5758a4e 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -53,7 +53,10 @@
 public abstract class VibrationEffect implements Parcelable {
     // Stevens' coefficient to scale the perceived vibration intensity.
     private static final float SCALE_GAMMA = 0.65f;
-
+    // If a vibration is playing for longer than 1s, it's probably not haptic feedback
+    private static final long MAX_HAPTIC_FEEDBACK_DURATION = 1000;
+    // If a vibration is playing more than 3 constants, it's probably not haptic feedback
+    private static final long MAX_HAPTIC_FEEDBACK_COMPOSITION_SIZE = 3;
 
     /**
      * The default vibration strength of the device.
@@ -439,6 +442,20 @@
     public abstract long getDuration();
 
     /**
+     * Returns true if this effect could represent a touch haptic feedback.
+     *
+     * <p>It is strongly recommended that an instance of {@link VibrationAttributes} is specified
+     * for each vibration, with the correct usage. When a vibration is played with usage UNKNOWN,
+     * then this method will be used to classify the most common use case and make sure they are
+     * covered by the user settings for "Touch feedback".
+     *
+     * @hide
+     */
+    public boolean isHapticFeedbackCandidate() {
+        return false;
+    }
+
+    /**
      * Resolve default values into integer amplitude numbers.
      *
      * @param defaultAmplitude the default amplitude to apply, must be between 0 and
@@ -582,6 +599,7 @@
             return mRepeatIndex;
         }
 
+        /** @hide */
         @Override
         public void validate() {
             int segmentCount = mSegments.size();
@@ -620,6 +638,37 @@
             return totalDuration;
         }
 
+        /** @hide */
+        @Override
+        public boolean isHapticFeedbackCandidate() {
+            long totalDuration = getDuration();
+            if (totalDuration > MAX_HAPTIC_FEEDBACK_DURATION) {
+                // Vibration duration is known and is longer than the max duration used to classify
+                // haptic feedbacks (or repeating indefinitely with duration == Long.MAX_VALUE).
+                return false;
+            }
+            int segmentCount = mSegments.size();
+            if (segmentCount > MAX_HAPTIC_FEEDBACK_COMPOSITION_SIZE) {
+                // Vibration has some prebaked or primitive constants, it should be limited to the
+                // max composition size used to classify haptic feedbacks.
+                return false;
+            }
+            totalDuration = 0;
+            for (int i = 0; i < segmentCount; i++) {
+                if (!mSegments.get(i).isHapticFeedbackCandidate()) {
+                    // There is at least one segment that is not a candidate for a haptic feedback.
+                    return false;
+                }
+                long segmentDuration = mSegments.get(i).getDuration();
+                if (segmentDuration > 0) {
+                    totalDuration += segmentDuration;
+                }
+            }
+            // Vibration might still have some ramp or step segments, check the known duration.
+            return totalDuration <= MAX_HAPTIC_FEEDBACK_DURATION;
+        }
+
+        /** @hide */
         @NonNull
         @Override
         public Composed resolve(int defaultAmplitude) {
@@ -636,6 +685,7 @@
             return resolved;
         }
 
+        /** @hide */
         @NonNull
         @Override
         public Composed scale(float scaleFactor) {
@@ -652,6 +702,7 @@
             return scaled;
         }
 
+        /** @hide */
         @NonNull
         @Override
         public Composed applyEffectStrength(int effectStrength) {
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index aa9028e..c67c82e 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -330,16 +330,15 @@
      *
      * @param alwaysOnId The board-specific always-on ID to configure.
      * @param effect     Vibration effect to assign to always-on id. Passing null will disable it.
-     * @param attributes {@link AudioAttributes} corresponding to the vibration. For example,
-     *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
-     *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
-     *                   vibrations associated with incoming calls. May only be null when effect is
-     *                   null.
+     * @param attributes {@link VibrationAttributes} corresponding to the vibration. For example,
+     *                   specify {@link VibrationAttributes#USAGE_ALARM} for alarm vibrations or
+     *                   {@link VibrationAttributes#USAGE_RINGTONE} for vibrations associated with
+     *                   incoming calls. May only be null when effect is null.
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
     public boolean setAlwaysOnEffect(int alwaysOnId, @Nullable VibrationEffect effect,
-            @Nullable AudioAttributes attributes) {
+            @Nullable VibrationAttributes attributes) {
         return setAlwaysOnEffect(Process.myUid(), mPackageName, alwaysOnId, effect, attributes);
     }
 
@@ -348,7 +347,7 @@
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)
     public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId,
-            @Nullable VibrationEffect effect, @Nullable AudioAttributes attributes) {
+            @Nullable VibrationEffect effect, @Nullable VibrationAttributes attributes) {
         Log.w(TAG, "Always-on effects aren't supported");
         return false;
     }
@@ -378,7 +377,7 @@
      *                     specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
      *                     {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
      *                     vibrations associated with incoming calls.
-     * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
+     * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead.
      */
     @Deprecated
     @RequiresPermission(android.Manifest.permission.VIBRATE)
@@ -444,7 +443,7 @@
      *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
      *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
      *                   vibrations associated with incoming calls.
-     * @deprecated Use {@link #vibrate(VibrationEffect, AudioAttributes)} instead.
+     * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead.
      */
     @Deprecated
     @RequiresPermission(android.Manifest.permission.VIBRATE)
@@ -473,7 +472,7 @@
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE)
     public void vibrate(VibrationEffect vibe) {
-        vibrate(vibe, null);
+        vibrate(vibe, new VibrationAttributes.Builder().build());
     }
 
     /**
@@ -487,35 +486,40 @@
      *                   specify {@link AudioAttributes#USAGE_ALARM} for alarm vibrations or
      *                   {@link AudioAttributes#USAGE_NOTIFICATION_RINGTONE} for
      *                   vibrations associated with incoming calls.
+     * @deprecated Use {@link #vibrate(VibrationEffect, VibrationAttributes)} instead.
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE)
     public void vibrate(VibrationEffect vibe, AudioAttributes attributes) {
+        vibrate(vibe,
+                attributes == null
+                        ? new VibrationAttributes.Builder().build()
+                        : new VibrationAttributes.Builder(attributes).build());
+    }
+
+    /**
+     * Vibrate with a given effect.
+     *
+     * <p>The app should be in foreground for the vibration to happen. Background apps should
+     * specify a ringtone, notification or alarm usage in order to vibrate.</p>
+     *
+     * @param vibe       {@link VibrationEffect} describing the vibration to be performed.
+     * @param attributes {@link VibrationAttributes} corresponding to the vibration. For example,
+     *                   specify {@link VibrationAttributes#USAGE_ALARM} for alarm vibrations or
+     *                   {@link VibrationAttributes#USAGE_RINGTONE} for vibrations associated with
+     *                   incoming calls.
+     */
+    @RequiresPermission(android.Manifest.permission.VIBRATE)
+    public void vibrate(@NonNull VibrationEffect vibe, @NonNull VibrationAttributes attributes) {
         vibrate(Process.myUid(), mPackageName, vibe, null, attributes);
     }
 
     /**
-     * Like {@link #vibrate(VibrationEffect, AudioAttributes)}, but allows the
+     * Like {@link #vibrate(VibrationEffect, VibrationAttributes)}, but allows the
      * caller to specify the vibration is owned by someone else and set reason for vibration.
      *
      * @hide
      */
     @RequiresPermission(android.Manifest.permission.VIBRATE)
-    public final void vibrate(int uid, String opPkg, VibrationEffect vibe,
-            String reason, AudioAttributes attributes) {
-        if (attributes == null) {
-            attributes = new AudioAttributes.Builder().build();
-        }
-        VibrationAttributes attr = new VibrationAttributes.Builder(attributes, vibe).build();
-        vibrate(uid, opPkg, vibe, reason, attr);
-    }
-
-    /**
-     * Like {@link #vibrate(int, String, VibrationEffect, String, AudioAttributes)}, but allows the
-     * caller to specify {@link VibrationAttributes} instead of {@link AudioAttributes}.
-     *
-     * @hide
-     */
-    @RequiresPermission(android.Manifest.permission.VIBRATE)
     public abstract void vibrate(int uid, String opPkg, @NonNull VibrationEffect vibe,
             String reason, @NonNull VibrationAttributes attributes);
 
diff --git a/core/java/android/os/storage/IStorageManager.aidl b/core/java/android/os/storage/IStorageManager.aidl
index fbac954..bff5c62 100644
--- a/core/java/android/os/storage/IStorageManager.aidl
+++ b/core/java/android/os/storage/IStorageManager.aidl
@@ -90,9 +90,9 @@
      */
     int changeEncryptionPassword(int type, in String password) = 28;
     /**
-     * Returns list of all mountable volumes.
+     * Returns list of all mountable volumes for the specified userId
      */
-    StorageVolume[] getVolumeList(int uid, in String packageName, int flags) = 29;
+    StorageVolume[] getVolumeList(int userId, in String callingPackage, int flags) = 29;
     /**
      * Determines the encryption state of the volume.
      * @return a numerical value. See {@code ENCRYPTION_STATE_*} for possible
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 77c794c..627e09e 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1391,13 +1391,7 @@
                 }
                 packageName = packageNames[0];
             }
-            final int uid = ActivityThread.getPackageManager().getPackageUid(packageName,
-                    PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
-            if (uid <= 0) {
-                Log.w(TAG, "Missing UID; no storage volumes available");
-                return new StorageVolume[0];
-            }
-            return storageManager.getVolumeList(uid, packageName, flags);
+            return storageManager.getVolumeList(userId, packageName, flags);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index f57d157..39a2e13 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -56,11 +56,12 @@
  * <ul>
  * <li>{@link #MOUNT_FLAG_PRIMARY} means the volume provides primary external
  * storage, historically found at {@code /sdcard}.
- * <li>{@link #MOUNT_FLAG_VISIBLE} means the volume is visible to third-party
- * apps for direct filesystem access. The system should send out relevant
- * storage broadcasts and index any media on visible volumes. Visible volumes
- * are considered a more stable part of the device, which is why we take the
- * time to index them. In particular, transient volumes like USB OTG devices
+ * <li>{@link #MOUNT_FLAG_VISIBLE_FOR_READ} and
+ * {@link #MOUNT_FLAG_VISIBLE_FOR_WRITE} mean the volume is visible to
+ * third-party apps for direct filesystem access. The system should send out
+ * relevant storage broadcasts and index any media on visible volumes. Visible
+ * volumes are considered a more stable part of the device, which is why we take
+ * the time to index them. In particular, transient volumes like USB OTG devices
  * <em>should not</em> be marked as visible; their contents should be surfaced
  * to apps through the Storage Access Framework.
  * </ul>
@@ -100,7 +101,8 @@
     public static final int STATE_BAD_REMOVAL = IVold.VOLUME_STATE_BAD_REMOVAL;
 
     public static final int MOUNT_FLAG_PRIMARY = IVold.MOUNT_FLAG_PRIMARY;
-    public static final int MOUNT_FLAG_VISIBLE = IVold.MOUNT_FLAG_VISIBLE;
+    public static final int MOUNT_FLAG_VISIBLE_FOR_READ = IVold.MOUNT_FLAG_VISIBLE_FOR_READ;
+    public static final int MOUNT_FLAG_VISIBLE_FOR_WRITE = IVold.MOUNT_FLAG_VISIBLE_FOR_WRITE;
 
     private static SparseArray<String> sStateToEnvironment = new SparseArray<>();
     private static ArrayMap<String, String> sEnvironmentToBroadcast = new ArrayMap<>();
@@ -312,17 +314,31 @@
         return isPrimary() && (getType() == TYPE_PUBLIC);
     }
 
-    @UnsupportedAppUsage
-    public boolean isVisible() {
-        return (mountFlags & MOUNT_FLAG_VISIBLE) != 0;
+    private boolean isVisibleForRead() {
+        return (mountFlags & MOUNT_FLAG_VISIBLE_FOR_READ) != 0;
     }
 
-    public boolean isVisibleForUser(int userId) {
-        if ((type == TYPE_PUBLIC || type == TYPE_STUB || type == TYPE_EMULATED)
-                && mountUserId == userId) {
-            return isVisible();
+    private boolean isVisibleForWrite() {
+        return (mountFlags & MOUNT_FLAG_VISIBLE_FOR_WRITE) != 0;
+    }
+
+    @UnsupportedAppUsage
+    public boolean isVisible() {
+        return isVisibleForRead() || isVisibleForWrite();
+    }
+
+    private boolean isVolumeSupportedForUser(int userId) {
+        if (mountUserId != userId) {
+            return false;
         }
-        return false;
+        return type == TYPE_PUBLIC || type == TYPE_STUB || type == TYPE_EMULATED;
+    }
+
+    /**
+     * Returns {@code true} if this volume is visible for {@code userId}, {@code false} otherwise.
+     */
+    public boolean isVisibleForUser(int userId) {
+        return isVolumeSupportedForUser(userId) && isVisible();
     }
 
     /**
@@ -335,12 +351,12 @@
     }
 
     public boolean isVisibleForRead(int userId) {
-        return isVisibleForUser(userId);
+        return isVolumeSupportedForUser(userId) && isVisibleForRead();
     }
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     public boolean isVisibleForWrite(int userId) {
-        return isVisibleForUser(userId);
+        return isVolumeSupportedForUser(userId) && isVisibleForWrite();
     }
 
     @UnsupportedAppUsage
diff --git a/core/java/android/os/vibrator/PrebakedSegment.java b/core/java/android/os/vibrator/PrebakedSegment.java
index 78b4346..30f5a5c 100644
--- a/core/java/android/os/vibrator/PrebakedSegment.java
+++ b/core/java/android/os/vibrator/PrebakedSegment.java
@@ -67,17 +67,38 @@
         return -1;
     }
 
+    /** @hide */
+    @Override
+    public boolean isHapticFeedbackCandidate() {
+        switch (mEffectId) {
+            case VibrationEffect.EFFECT_CLICK:
+            case VibrationEffect.EFFECT_DOUBLE_CLICK:
+            case VibrationEffect.EFFECT_HEAVY_CLICK:
+            case VibrationEffect.EFFECT_POP:
+            case VibrationEffect.EFFECT_TEXTURE_TICK:
+            case VibrationEffect.EFFECT_THUD:
+            case VibrationEffect.EFFECT_TICK:
+                return true;
+            default:
+                // VibrationEffect.RINGTONES are not segments that could represent a haptic feedback
+                return false;
+        }
+    }
+
+    /** @hide */
     @Override
     public boolean hasNonZeroAmplitude() {
         return true;
     }
 
+    /** @hide */
     @NonNull
     @Override
     public PrebakedSegment resolve(int defaultAmplitude) {
         return this;
     }
 
+    /** @hide */
     @NonNull
     @Override
     public PrebakedSegment scale(float scaleFactor) {
@@ -85,6 +106,7 @@
         return this;
     }
 
+    /** @hide */
     @NonNull
     @Override
     public PrebakedSegment applyEffectStrength(int effectStrength) {
@@ -105,16 +127,17 @@
         }
     }
 
+    /** @hide */
     @Override
     public void validate() {
         switch (mEffectId) {
             case VibrationEffect.EFFECT_CLICK:
             case VibrationEffect.EFFECT_DOUBLE_CLICK:
-            case VibrationEffect.EFFECT_TICK:
+            case VibrationEffect.EFFECT_HEAVY_CLICK:
+            case VibrationEffect.EFFECT_POP:
             case VibrationEffect.EFFECT_TEXTURE_TICK:
             case VibrationEffect.EFFECT_THUD:
-            case VibrationEffect.EFFECT_POP:
-            case VibrationEffect.EFFECT_HEAVY_CLICK:
+            case VibrationEffect.EFFECT_TICK:
                 break;
             default:
                 int[] ringtones = VibrationEffect.RINGTONES;
diff --git a/core/java/android/os/vibrator/PrimitiveSegment.java b/core/java/android/os/vibrator/PrimitiveSegment.java
index 2ef29cb..58ca978 100644
--- a/core/java/android/os/vibrator/PrimitiveSegment.java
+++ b/core/java/android/os/vibrator/PrimitiveSegment.java
@@ -67,18 +67,27 @@
         return -1;
     }
 
+    /** @hide */
+    @Override
+    public boolean isHapticFeedbackCandidate() {
+        return true;
+    }
+
+    /** @hide */
     @Override
     public boolean hasNonZeroAmplitude() {
         // Every primitive plays a vibration with a non-zero amplitude, even at scale == 0.
         return true;
     }
 
+    /** @hide */
     @NonNull
     @Override
     public PrimitiveSegment resolve(int defaultAmplitude) {
         return this;
     }
 
+    /** @hide */
     @NonNull
     @Override
     public PrimitiveSegment scale(float scaleFactor) {
@@ -86,12 +95,14 @@
                 mDelay);
     }
 
+    /** @hide */
     @NonNull
     @Override
     public PrimitiveSegment applyEffectStrength(int effectStrength) {
         return this;
     }
 
+    /** @hide */
     @Override
     public void validate() {
         Preconditions.checkArgumentInRange(mPrimitiveId, VibrationEffect.Composition.PRIMITIVE_NOOP,
diff --git a/core/java/android/os/vibrator/RampSegment.java b/core/java/android/os/vibrator/RampSegment.java
index aad87c5..3ec5636 100644
--- a/core/java/android/os/vibrator/RampSegment.java
+++ b/core/java/android/os/vibrator/RampSegment.java
@@ -87,11 +87,19 @@
         return mDuration;
     }
 
+    /** @hide */
+    @Override
+    public boolean isHapticFeedbackCandidate() {
+        return true;
+    }
+
+    /** @hide */
     @Override
     public boolean hasNonZeroAmplitude() {
         return mStartAmplitude > 0 || mEndAmplitude > 0;
     }
 
+    /** @hide */
     @Override
     public void validate() {
         Preconditions.checkArgumentNonnegative(mDuration,
@@ -100,7 +108,7 @@
         Preconditions.checkArgumentInRange(mEndAmplitude, 0f, 1f, "endAmplitude");
     }
 
-
+    /** @hide */
     @NonNull
     @Override
     public RampSegment resolve(int defaultAmplitude) {
@@ -108,6 +116,7 @@
         return this;
     }
 
+    /** @hide */
     @NonNull
     @Override
     public RampSegment scale(float scaleFactor) {
@@ -121,6 +130,7 @@
                 mDuration);
     }
 
+    /** @hide */
     @NonNull
     @Override
     public RampSegment applyEffectStrength(int effectStrength) {
diff --git a/core/java/android/os/vibrator/StepSegment.java b/core/java/android/os/vibrator/StepSegment.java
index 11209e0..69a381f 100644
--- a/core/java/android/os/vibrator/StepSegment.java
+++ b/core/java/android/os/vibrator/StepSegment.java
@@ -73,12 +73,20 @@
         return mDuration;
     }
 
+    /** @hide */
+    @Override
+    public boolean isHapticFeedbackCandidate() {
+        return true;
+    }
+
+    /** @hide */
     @Override
     public boolean hasNonZeroAmplitude() {
         // DEFAULT_AMPLITUDE == -1 is still a non-zero amplitude that will be resolved later.
         return Float.compare(mAmplitude, 0) != 0;
     }
 
+    /** @hide */
     @Override
     public void validate() {
         Preconditions.checkArgumentNonnegative(mDuration,
@@ -88,6 +96,7 @@
         }
     }
 
+    /** @hide */
     @NonNull
     @Override
     public StepSegment resolve(int defaultAmplitude) {
@@ -103,6 +112,7 @@
                 mDuration);
     }
 
+    /** @hide */
     @NonNull
     @Override
     public StepSegment scale(float scaleFactor) {
@@ -113,6 +123,7 @@
                 mDuration);
     }
 
+    /** @hide */
     @NonNull
     @Override
     public StepSegment applyEffectStrength(int effectStrength) {
diff --git a/core/java/android/os/vibrator/VibrationEffectSegment.java b/core/java/android/os/vibrator/VibrationEffectSegment.java
index 5b42845..979c447 100644
--- a/core/java/android/os/vibrator/VibrationEffectSegment.java
+++ b/core/java/android/os/vibrator/VibrationEffectSegment.java
@@ -57,10 +57,26 @@
      */
     public abstract long getDuration();
 
-    /** Returns true if this segment plays at a non-zero amplitude at some point. */
+    /**
+     * Returns true if this segment could be a haptic feedback effect candidate.
+     *
+     * @see VibrationEffect#isHapticFeedbackCandidate()
+     * @hide
+     */
+    public abstract boolean isHapticFeedbackCandidate();
+
+    /**
+     * Returns true if this segment plays at a non-zero amplitude at some point.
+     *
+     * @hide
+     */
     public abstract boolean hasNonZeroAmplitude();
 
-    /** Validates the segment, throwing exceptions if any parameter is invalid. */
+    /**
+     * Validates the segment, throwing exceptions if any parameter is invalid.
+     *
+     * @hide
+     */
     public abstract void validate();
 
     /**
@@ -68,6 +84,8 @@
      *
      * <p>This might fail with {@link IllegalArgumentException} if value is non-positive or larger
      * than {@link VibrationEffect#MAX_AMPLITUDE}.
+     *
+     * @hide
      */
     @NonNull
     public abstract <T extends VibrationEffectSegment> T resolve(int defaultAmplitude);
@@ -77,6 +95,8 @@
      *
      * @param scaleFactor scale factor to be applied to the intensity. Values within [0,1) will
      *                    scale down the intensity, values larger than 1 will scale up
+     *
+     * @hide
      */
     @NonNull
     public abstract <T extends VibrationEffectSegment> T scale(float scaleFactor);
@@ -86,6 +106,8 @@
      *
      * @param effectStrength new effect strength to be applied, one of
      *                       VibrationEffect.EFFECT_STRENGTH_*.
+     *
+     * @hide
      */
     @NonNull
     public abstract <T extends VibrationEffectSegment> T applyEffectStrength(int effectStrength);
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index f8aa98e..5036abc 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -8788,7 +8788,12 @@
         public static final String KEY_DEFAULT_ACCOUNT = "key_default_account";
 
         /**
-         * Return the account that was set to default account for new contacts.
+         * Get the account that is set as the default account for new contacts, which should be
+         * initially selected when creating a new contact on contact management apps.
+         *
+         * @param resolver the ContentResolver to query.
+         * @return the default account for new contacts, or null if it's not set or set to NULL
+         * account.
          */
         @Nullable
         public static Account getDefaultAccount(@NonNull ContentResolver resolver) {
@@ -8798,8 +8803,10 @@
         }
 
         /**
-         * Set the account to be the default account for new contacts.
+         * Sets the account as the default account that should be initially selected
+         * when creating a new contact on contact management apps.
          *
+         * @param resolver the ContentResolver to query.
          * @param account the account to be set to default.
          * @hide
          */
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index dfc4fa7..7979256 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -54,6 +54,7 @@
 import android.database.SQLException;
 import android.location.ILocationManager;
 import android.location.LocationManager;
+import android.media.AudioManager;
 import android.net.ConnectivityManager;
 import android.net.NetworkScoreManager;
 import android.net.Uri;
@@ -269,6 +270,16 @@
     public static final String EXTRA_NETWORK_TEMPLATE = "network_template";
 
     /**
+     * Activity Action: Show One-handed mode Settings page.
+     * <p>
+     * Input: Nothing
+     * <p>
+     * Output: Nothing
+     * @hide
+     */
+    public static final String ACTION_ONE_HANDED_SETTINGS =
+            "android.settings.action.ONE_HANDED_SETTINGS";
+    /**
      * The return values for {@link Settings.Config#set}
      * @hide
      */
@@ -379,6 +390,21 @@
             "android.settings.REDUCE_BRIGHT_COLORS_SETTINGS";
 
     /**
+     * Activity Action: Show settings to allow configuration of Color inversion.
+     * <p>
+     * In some cases, a matching Activity may not exist, so ensure you
+     * safeguard against this.
+     * <p>
+     * Input: Nothing.
+     * <p>
+     * Output: Nothing.
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_COLOR_INVERSION_SETTINGS =
+            "android.settings.COLOR_INVERSION_SETTINGS";
+
+    /**
      * Activity Action: Show settings to control access to usage information.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you
@@ -3607,6 +3633,12 @@
 
         private static boolean putStringForUser(ContentResolver resolver, String name, String value,
                 int userHandle, boolean overrideableByRestore) {
+            return putStringForUser(resolver, name, value, /* tag= */ null,
+                    /* makeDefault= */ false, userHandle, overrideableByRestore);
+        }
+
+        private static boolean putStringForUser(ContentResolver resolver, String name, String value,
+                String tag, boolean makeDefault, int userHandle, boolean overrideableByRestore) {
             if (MOVED_TO_SECURE.contains(name)) {
                 Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.System"
                         + " to android.provider.Settings.Secure, value is unchanged.");
@@ -3617,8 +3649,8 @@
                         + " to android.provider.Settings.Global, value is unchanged.");
                 return false;
             }
-            return sNameValueCache.putStringForUser(resolver, name, value, null, false, userHandle,
-                    overrideableByRestore);
+            return sNameValueCache.putStringForUser(resolver, name, value, tag, makeDefault,
+                    userHandle, overrideableByRestore);
         }
 
         /**
@@ -4454,6 +4486,15 @@
         public static final String VIBRATE_ON = "vibrate_on";
 
         /**
+         * Whether applying ramping ringer on incoming phone call ringtone.
+         * <p>1 = apply ramping ringer
+         * <p>0 = do not apply ramping ringer
+         * @hide
+         */
+        @Readable
+        public static final String APPLY_RAMPING_RINGER = "apply_ramping_ringer";
+
+        /**
          * If 1, redirects the system vibrator to all currently attached input devices
          * that support vibration.  If there are no such input devices, then the system
          * vibrator is used instead.
@@ -4522,6 +4563,25 @@
                 "haptic_feedback_intensity";
 
         /**
+         * The intensity of haptic feedback vibrations for interaction with hardware components from
+         * the device, like buttons and sensors, if configurable.
+         *
+         * Not all devices are capable of changing their feedback intensity; on these devices
+         * there will likely be no difference between the various vibration intensities except for
+         * intensity 0 (off) and the rest.
+         *
+         * <b>Values:</b><br/>
+         * 0 - Vibration is disabled<br/>
+         * 1 - Weak vibrations<br/>
+         * 2 - Medium vibrations<br/>
+         * 3 - Strong vibrations
+         * @hide
+         */
+        @Readable
+        public static final String HARDWARE_HAPTIC_FEEDBACK_INTENSITY =
+                "hardware_haptic_feedback_intensity";
+
+        /**
          * Ringer volume. This is used internally, changing this value will not
          * change the volume. See AudioManager.
          *
@@ -5304,6 +5364,7 @@
             PUBLIC_SETTINGS.add(HAPTIC_FEEDBACK_ENABLED);
             PUBLIC_SETTINGS.add(SHOW_WEB_SUGGESTIONS);
             PUBLIC_SETTINGS.add(VIBRATE_WHEN_RINGING);
+            PUBLIC_SETTINGS.add(APPLY_RAMPING_RINGER);
         }
 
         /**
@@ -5841,6 +5902,10 @@
         }
 
         /** @hide */
+        public static void getMovedToSystemSettings(Set<String> outKeySet) {
+        }
+
+        /** @hide */
         public static void clearProviderForTest() {
             sProviderHolder.clearProviderForTest();
             sNameValueCache.clearGenerationTrackerForTest();
@@ -9658,6 +9723,14 @@
         public static final String LOCKSCREEN_SHOW_WALLET = "lockscreen_show_wallet";
 
         /**
+         * Whether to use the lockscreen double-line clock
+         *
+         * @hide
+         */
+        public static final String LOCKSCREEN_USE_DOUBLE_LINE_CLOCK =
+                "lockscreen_use_double_line_clock";
+
+        /**
          * Specifies whether the web action API is enabled.
          *
          * @hide
@@ -10430,7 +10503,9 @@
          * Whether applying ramping ringer on incoming phone call ringtone.
          * <p>1 = apply ramping ringer
          * <p>0 = do not apply ramping ringer
+         * @deprecated Use {@link AudioManager#isRampingRingerEnabled()} instead
          */
+        @Deprecated
         @Readable
         public static final String APPLY_RAMPING_RINGER = "apply_ramping_ringer";
 
@@ -11939,8 +12014,10 @@
          * Value to specify whether network quality scores and badging should be shown in the UI.
          *
          * Type: int (0 for false, 1 for true)
+         * @deprecated {@code NetworkScoreManager} is deprecated.
          * @hide
          */
+        @Deprecated
         @Readable
         public static final String NETWORK_SCORING_UI_ENABLED = "network_scoring_ui_enabled";
 
@@ -11949,8 +12026,10 @@
          * when generating SSID only bases score curves.
          *
          * Type: long
+         * @deprecated {@code NetworkScoreManager} is deprecated.
          * @hide
          */
+        @Deprecated
         @Readable
         public static final String SPEED_LABEL_CACHE_EVICTION_AGE_MILLIS =
                 "speed_label_cache_eviction_age_millis";
@@ -11983,8 +12062,10 @@
          * {@link NetworkScoreManager#setActiveScorer(String)} to write it.
          *
          * Type: string - package name
+         * @deprecated {@code NetworkScoreManager} is deprecated.
          * @hide
          */
+        @Deprecated
         @Readable
         public static final String NETWORK_RECOMMENDATIONS_PACKAGE =
                 "network_recommendations_package";
@@ -11994,8 +12075,10 @@
          * networks automatically.
          *
          * Type: string package name or null if the feature is either not provided or disabled.
+         * @deprecated {@code NetworkScoreManager} is deprecated.
          * @hide
          */
+        @Deprecated
         @TestApi
         @Readable
         public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
@@ -12005,8 +12088,10 @@
          * {@link com.android.server.wifi.RecommendedNetworkEvaluator}.
          *
          * Type: long
+         * @deprecated {@code NetworkScoreManager} is deprecated.
          * @hide
          */
+        @Deprecated
         @Readable
         public static final String RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS =
                 "recommended_network_evaluator_cache_expiry_ms";
@@ -13587,7 +13672,7 @@
          * Whether of not to send keycode sleep for ungaze when Home is the foreground activity on
          * watch type devices.
          * Type: int (0 for false, 1 for true)
-         * Default: 0
+         * Default: 1
          * @hide
          */
         @Readable
@@ -15080,22 +15165,6 @@
                 "max_sound_trigger_detection_service_ops_per_day";
 
         /**
-         * Setting indicating the name of the Wear OS app package containing the device's sysui.
-         *
-         * @hide
-         */
-        public static final String CLOCKWORK_SYSUI_PACKAGE_NAME =
-                "clockwork_sysui_package_name";
-
-        /**
-         * Setting indicating the name of the main activity of the Wear OS sysui.
-         *
-         * @hide
-         */
-        public static final String CLOCKWORK_SYSUI_MAIN_ACTIVITY_NAME =
-                "clockwork_sysui_main_activity_name";
-
-        /**
          * Setting to determine if the Clockwork Home application is ready.
          *
          * <p>
@@ -15225,12 +15294,24 @@
             MOVED_TO_SECURE.add(Global.NOTIFICATION_BUBBLES);
         }
 
+        // Certain settings have been moved from global to the per-user system namespace
+        private static final HashSet<String> MOVED_TO_SYSTEM;
+        static {
+            MOVED_TO_SYSTEM = new HashSet<>(1);
+            MOVED_TO_SYSTEM.add(Global.APPLY_RAMPING_RINGER);
+        }
+
         /** @hide */
         public static void getMovedToSecureSettings(Set<String> outKeySet) {
             outKeySet.addAll(MOVED_TO_SECURE);
         }
 
         /** @hide */
+        public static void getMovedToSystemSettings(Set<String> outKeySet) {
+            outKeySet.addAll(MOVED_TO_SYSTEM);
+        }
+
+        /** @hide */
         public static void clearProviderForTest() {
             sProviderHolder.clearProviderForTest();
             sNameValueCache.clearGenerationTrackerForTest();
@@ -15262,6 +15343,11 @@
                         + " to android.provider.Settings.Secure, returning read-only value.");
                 return Secure.getStringForUser(resolver, name, userHandle);
             }
+            if (MOVED_TO_SYSTEM.contains(name)) {
+                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Global"
+                        + " to android.provider.Settings.System, returning read-only value.");
+                return System.getStringForUser(resolver, name, userHandle);
+            }
             return sNameValueCache.getStringForUser(resolver, name, userHandle);
         }
 
@@ -15426,6 +15512,13 @@
                 return Secure.putStringForUser(resolver, name, value, tag,
                         makeDefault, userHandle, overrideableByRestore);
             }
+            // Global and System have the same access policy so we can forward writes
+            if (MOVED_TO_SYSTEM.contains(name)) {
+                Log.w(TAG, "Setting " + name + " has moved from android.provider.Settings.Global"
+                        + " to android.provider.Settings.System, value is unchanged.");
+                return System.putStringForUser(resolver, name, value, tag,
+                        makeDefault, userHandle, overrideableByRestore);
+            }
             return sNameValueCache.putStringForUser(resolver, name, value, tag,
                     makeDefault, userHandle, overrideableByRestore);
         }
@@ -16683,12 +16776,6 @@
             public static final String AMBIENT_FORCE_WHEN_DOCKED = "ambient_force_when_docked";
 
             /**
-             * The id of the gesture sensor.
-             * @hide
-             */
-            public static final String AMBIENT_GESTURE_SENSOR_ID = "ambient_gesture_sensor_id";
-
-            /**
              * Whether the ambient low bit mode is enabled.
              * @hide
              */
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 1b38f59..5d84af0 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -3584,6 +3584,23 @@
                 "content://telephony/carriers/enforce_managed");
 
         /**
+         * The {@code content://} style URL for the perferred APN used for internet.
+         *
+         * @hide
+         */
+        public static final Uri PREFERRED_APN_URI = Uri.parse(
+                "content://telephony/carriers/preferapn/subId/");
+
+        /**
+         * The {@code content://} style URL for the perferred APN set id.
+         *
+         * @hide
+         */
+        public static final Uri PREFERRED_APN_SET_URI = Uri.parse(
+                "content://telephony/carriers/preferapnset/subId/");
+
+
+        /**
          * The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced.
          * @hide
          */
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt b/core/java/android/security/attestationverification/AttestationProfile.aidl
similarity index 84%
copy from packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
copy to core/java/android/security/attestationverification/AttestationProfile.aidl
index bacc66b..51696a9 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
+++ b/core/java/android/security/attestationverification/AttestationProfile.aidl
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.flags
+package android.security.attestationverification;
 
-interface FlagWriter {
-    fun setEnabled(key: Int, value: Boolean) {}
-}
\ No newline at end of file
+/**
+ * {@hide}
+ */
+parcelable AttestationProfile;
diff --git a/core/java/android/security/attestationverification/AttestationProfile.java b/core/java/android/security/attestationverification/AttestationProfile.java
new file mode 100644
index 0000000..7a43dac
--- /dev/null
+++ b/core/java/android/security/attestationverification/AttestationProfile.java
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2021 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 android.security.attestationverification;
+
+import static android.security.attestationverification.AttestationVerificationManager.PROFILE_APP_DEFINED;
+import static android.security.attestationverification.AttestationVerificationManager.PROFILE_UNKNOWN;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcelable;
+import android.security.attestationverification.AttestationVerificationManager.AttestationProfileId;
+import android.util.Log;
+
+import com.android.internal.util.DataClass;
+
+
+/**
+ * An attestation profile defining the security requirements for verifying the attestation of a
+ * remote compute environment.
+ *
+ * <p>This class is immutable and thread-safe. When checking this profile against an expected
+ * profile, it is recommended to construct the expected profile and compare them with {@code
+ * equals()}.
+ *
+ * @hide
+ * @see AttestationVerificationManager
+ */
+@DataClass(
+        genConstructor = false,
+        genEqualsHashCode = true
+)
+public final class AttestationProfile implements Parcelable {
+
+    private static final String TAG = "AVF";
+
+    /**
+     * The ID of a system-defined attestation profile.
+     *
+     * See constants in {@link AttestationVerificationManager} prefixed with {@code PROFILE_}. If
+     * this has the value of {@link AttestationVerificationManager#PROFILE_APP_DEFINED}, then the
+     * packageName and profileName are non-null.
+     */
+    @AttestationProfileId
+    private final int mAttestationProfileId;
+
+    /**
+     * The package name of a app-defined attestation profile.
+     *
+     * This value will be null unless the value of attestationProfileId is {@link
+     * AttestationVerificationManager#PROFILE_APP_DEFINED}.
+     */
+    @Nullable
+    private final String mPackageName;
+
+
+    /**
+     * The name of an app-defined attestation profile.
+     *
+     * This value will be null unless the value of attestationProfileId is {@link
+     * AttestationVerificationManager#PROFILE_APP_DEFINED}.
+     */
+    @Nullable
+    private final String mProfileName;
+
+    private AttestationProfile(
+            @AttestationProfileId int attestationProfileId,
+            @Nullable String packageName,
+            @Nullable String profileName) {
+        mAttestationProfileId = attestationProfileId;
+        mPackageName = packageName;
+        mProfileName = profileName;
+    }
+
+    /**
+     * Create a profile with the given id.
+     *
+     * <p>This constructor is for specifying a profile which is defined by the system. These are
+     * available as constants in the {@link AttestationVerificationManager} class prefixed with
+     * {@code PROFILE_}.
+     *
+     * @param attestationProfileId the ID of the system-defined profile
+     * @throws IllegalArgumentException when called with
+     * {@link AttestationVerificationManager#PROFILE_APP_DEFINED}
+     *                                  (use {@link #AttestationProfile(String, String)})
+     */
+    public AttestationProfile(@AttestationProfileId int attestationProfileId) {
+        this(attestationProfileId, null, null);
+        if (attestationProfileId == PROFILE_APP_DEFINED) {
+            throw new IllegalArgumentException("App-defined profiles must be specified with the "
+                    + "constructor AttestationProfile#constructor(String, String)");
+        }
+    }
+
+    /**
+     * Create a profile with the given package name and profile name.
+     *
+     * <p>This constructor is for specifying a profile defined by an app. The packageName must
+     * match the package name of the app that defines the profile (as specified in the {@code
+     * package} attribute of the {@code
+     * <manifest>} tag in the app's manifest. The profile name matches the {@code name} attribute
+     * of the {@code <attestation-profile>} tag.
+     *
+     * <p>Apps must declare profiles in their manifest as an {@code <attestation-profile>} element.
+     * However, this constructor does not verify that such a profile exists. If the profile does not
+     * exist, verifications will fail.
+     *
+     * @param packageName the package name of the app defining the profile
+     * @param profileName the name of the profile
+     */
+    public AttestationProfile(@NonNull String packageName, @NonNull String profileName) {
+        this(PROFILE_APP_DEFINED, packageName, profileName);
+        if (packageName == null || profileName == null) {
+            throw new IllegalArgumentException("Both packageName and profileName must be non-null");
+        }
+    }
+
+    @Override
+    public String toString() {
+        if (mAttestationProfileId == PROFILE_APP_DEFINED) {
+            return "AttestationProfile(package=" + mPackageName + ", name=" + mProfileName + ")";
+        } else {
+            String humanReadableProfileId;
+            switch (mAttestationProfileId) {
+                case PROFILE_UNKNOWN:
+                    humanReadableProfileId = "PROFILE_UNKNOWN";
+                    break;
+                default:
+                    Log.e(TAG, "ERROR: Missing case in AttestationProfile#toString");
+                    humanReadableProfileId = "ERROR";
+            }
+            return "AttestationProfile(" + humanReadableProfileId + "/" + mAttestationProfileId
+                    + ")";
+        }
+    }
+
+
+    // Code below generated by codegen v1.0.23.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/security
+    // /attestationverification/AttestationProfile.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /**
+     * The ID of a system-defined attestation profile.
+     *
+     * See constants in {@link AttestationVerificationManager} prefixed with {@code PROFILE_}. If
+     * this has the value of {@link AttestationVerificationManager#PROFILE_APP_DEFINED}, then the
+     * packageName and profileName are non-null.
+     */
+    @DataClass.Generated.Member
+    public @AttestationProfileId int getAttestationProfileId() {
+        return mAttestationProfileId;
+    }
+
+    /**
+     * The package name of a app-defined attestation profile.
+     *
+     * This value will be null unless the value of attestationProfileId is {@link
+     * AttestationVerificationManager#PROFILE_APP_DEFINED}.
+     */
+    @DataClass.Generated.Member
+    public @Nullable String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * The name of an app-defined attestation profile.
+     *
+     * This value will be null unless the value of attestationProfileId is {@link
+     * AttestationVerificationManager#PROFILE_APP_DEFINED}.
+     */
+    @DataClass.Generated.Member
+    public @Nullable String getProfileName() {
+        return mProfileName;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(AttestationProfile other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        AttestationProfile that = (AttestationProfile) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && mAttestationProfileId == that.mAttestationProfileId
+                && java.util.Objects.equals(mPackageName, that.mPackageName)
+                && java.util.Objects.equals(mProfileName, that.mProfileName);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + mAttestationProfileId;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mPackageName);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mProfileName);
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        byte flg = 0;
+        if (mPackageName != null) flg |= 0x2;
+        if (mProfileName != null) flg |= 0x4;
+        dest.writeByte(flg);
+        dest.writeInt(mAttestationProfileId);
+        if (mPackageName != null) dest.writeString(mPackageName);
+        if (mProfileName != null) dest.writeString(mProfileName);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ AttestationProfile(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        byte flg = in.readByte();
+        int attestationProfileId = in.readInt();
+        String packageName = (flg & 0x2) == 0 ? null : in.readString();
+        String profileName = (flg & 0x4) == 0 ? null : in.readString();
+
+        this.mAttestationProfileId = attestationProfileId;
+        com.android.internal.util.AnnotationValidations.validate(
+                AttestationProfileId.class, null, mAttestationProfileId);
+        this.mPackageName = packageName;
+        this.mProfileName = profileName;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<AttestationProfile> CREATOR
+            = new Parcelable.Creator<AttestationProfile>() {
+        @Override
+        public AttestationProfile[] newArray(int size) {
+            return new AttestationProfile[size];
+        }
+
+        @Override
+        public AttestationProfile createFromParcel(@NonNull android.os.Parcel in) {
+            return new AttestationProfile(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1633629498403L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/security/attestationverification/AttestationProfile.java",
+            inputSignatures = "private static final  java.lang.String TAG\nprivate final @android.security.attestationverification.AttestationVerificationManager.AttestationProfileId int mAttestationProfileId\nprivate final @android.annotation.Nullable java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mProfileName\npublic @java.lang.Override java.lang.String toString()\nclass AttestationProfile extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genEqualsHashCode=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/security/attestationverification/AttestationVerificationManager.java b/core/java/android/security/attestationverification/AttestationVerificationManager.java
new file mode 100644
index 0000000..db783ce
--- /dev/null
+++ b/core/java/android/security/attestationverification/AttestationVerificationManager.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2021 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 android.security.attestationverification;
+
+import android.Manifest;
+import android.annotation.CallbackExecutor;
+import android.annotation.CheckResult;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.content.Context;
+import android.os.Bundle;
+import android.os.ParcelDuration;
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.android.internal.infra.AndroidFuture;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.time.Duration;
+import java.util.concurrent.Executor;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiConsumer;
+
+/**
+ * Provides methods for verifying that attestations from remote compute environments meet minimum
+ * security requirements specified by attestation profiles.
+ *
+ * @hide
+ */
+@SystemService(Context.ATTESTATION_VERIFICATION_SERVICE)
+public class AttestationVerificationManager {
+
+    private static final String TAG = "AVF";
+    private static final Duration MAX_TOKEN_AGE = Duration.ofHours(1);
+
+    private final Context mContext;
+    private final IAttestationVerificationManagerService mService;
+
+    /**
+     * Verifies that {@code attestation} describes a computing environment that meets the
+     * requirements of {@code profile}, {@code localBindingType}, and {@code requirements}.
+     *
+     * <p>This method verifies that at least one system-registered {@linkplain
+     * AttestationVerificationService attestation verifier} associated with {@code profile} and
+     * {@code localBindingType} has verified that {@code attestation} attests that the remote
+     * environment matching the local binding data (determined by {@code localBindingType}) in
+     * {@code requirements} meets the requirements of the profile.
+     *
+     * <p>For successful verification, the {@code requirements} bundle must contain locally-known
+     * data which must match {@code attestation}. The required data in the bundle is defined by the
+     * {@code localBindingType} (see documentation for the type). Verifiers will fail to verify the
+     * attestation if the bundle contains unsupported data.
+     *
+     * <p>The {@code localBindingType} specifies how {@code attestation} is bound to a local
+     * secure channel endpoint or similar connection with the target remote environment described by
+     * the attestation. The binding is expected to be related to a cryptographic protocol, and each
+     * binding type requires specific arguments to be present in the {@code requirements} bundle. It
+     * is this binding to something known locally that ensures an attestation is not only valid, but
+     * is also associated with a particular connection.
+     *
+     * <p>The {@code callback} is called with a result and {@link VerificationToken} (which may be
+     * null). The result is an integer (see constants in this class with the prefix {@code RESULT_}.
+     * The result is {@link #RESULT_SUCCESS} when at least one verifier has passed its checks. The
+     * token may be used in calls to other parts of the system.
+     *
+     * <p>It's expected that a verifier will be able to decode and understand the passed values,
+     * otherwise fail to verify. {@code attestation} should contain some type data to prevent parse
+     * errors.
+     *
+     * <p>The values put into the {@code requirements} Bundle depend on the {@code
+     * localBindingType} used.
+     *
+     * @param profile          the attestation profile which defines the security requirements which
+     *                         must be met by the environment described by {@code attestation}
+     * @param localBindingType the type of the local binding data; see constants in this class with
+     *                         the prefix {@code TYPE_}
+     * @param requirements     a {@link Bundle} containing locally-known data which must match
+     *                         {@code attestation}
+     * @param attestation      attestation data which describes a remote computing environment
+     * @param executor         {@code callback} will be executed on this executor
+     * @param callback         will be called with the results of the verification
+     * @see AttestationVerificationService
+     */
+    @RequiresPermission(Manifest.permission.USE_ATTESTATION_VERIFICATION_SERVICE)
+    public void verifyAttestation(
+            @NonNull AttestationProfile profile,
+            @LocalBindingType int localBindingType,
+            @NonNull Bundle requirements,
+            @NonNull byte[] attestation,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull BiConsumer<@VerificationResult Integer, VerificationToken> callback) {
+        try {
+            AndroidFuture<IVerificationResult> resultCallback = new AndroidFuture<>();
+            resultCallback.thenAccept(result -> {
+                Log.d(TAG, "verifyAttestation result: " + result.resultCode + " / " + result.token);
+                executor.execute(() -> {
+                    callback.accept(result.resultCode, result.token);
+                });
+            });
+
+            mService.verifyAttestation(profile, localBindingType, requirements, attestation,
+                    resultCallback);
+
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Verifies that {@code token} is a valid token, returning the result contained in valid
+     * tokens.
+     *
+     * <p>This verifies that the token was issued by the platform and thus the system verified
+     * attestation data against the specified {@code profile}, {@code localBindingType}, and {@code
+     * requirements}. The value returned by this method is the same as the one originally returned
+     * when the token was generated. Callers of this method should not trust the provider of the
+     * token to also specify the profile, local binding type, or requirements, but instead have
+     * their own security requirements about these arguments.
+     *
+     * <p>This method, in contrast to {@code verifyAttestation}, executes synchronously and only
+     * checks that a previous verification succeeded. This allows callers to pass the token to
+     * others, including system APIs, without those components needing to re-verify the attestation
+     * data, an operation which can take several seconds.
+     *
+     * <p>When {@code maximumAge} is not specified (null), this method verifies the token was
+     * generated in the past hour. Otherwise, it verifies the token was generated between now and
+     * {@code maximumAge} ago. The maximum value of {@code maximumAge} is one hour; specifying a
+     * duration greater than one hour will result in an {@link IllegalArgumentException}.
+     *
+     * @param profile          the attestation profile which must be in the token
+     * @param localBindingType the local binding type which must be in the token
+     * @param requirements     the requirements which must be in the token
+     * @param token            the token to be verified
+     * @param maximumAge       the maximum age to accept for the token
+     */
+    @RequiresPermission(Manifest.permission.USE_ATTESTATION_VERIFICATION_SERVICE)
+    @CheckResult
+    @VerificationResult
+    public int verifyToken(
+            @NonNull AttestationProfile profile,
+            @LocalBindingType int localBindingType,
+            @NonNull Bundle requirements,
+            @NonNull VerificationToken token,
+            @Nullable Duration maximumAge) {
+        Duration usedMaximumAge;
+        if (maximumAge == null) {
+            usedMaximumAge = MAX_TOKEN_AGE;
+        } else {
+            if (maximumAge.compareTo(MAX_TOKEN_AGE) > 0) {
+                throw new IllegalArgumentException(
+                        "maximumAge cannot be greater than " + MAX_TOKEN_AGE + "; was "
+                                + maximumAge);
+            }
+            usedMaximumAge = maximumAge;
+        }
+
+        try {
+            AndroidFuture<Integer> resultCallback = new AndroidFuture<>();
+            resultCallback.orTimeout(5, TimeUnit.SECONDS);
+
+            mService.verifyToken(token, new ParcelDuration(usedMaximumAge), resultCallback);
+            return resultCallback.get(); // block on result callback
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        } catch (Throwable t) {
+            throw new RuntimeException("Error verifying token.", t);
+        }
+    }
+
+    /** @hide */
+    public AttestationVerificationManager(
+            @NonNull Context context,
+            @NonNull IAttestationVerificationManagerService service) {
+        this.mContext = context;
+        this.mService = service;
+    }
+
+    /** @hide */
+    @IntDef(
+            prefix = {"PROFILE_"},
+            value = {
+                    PROFILE_UNKNOWN,
+                    PROFILE_APP_DEFINED,
+                    PROFILE_SELF_TRUSTED,
+                    PROFILE_PEER_DEVICE,
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AttestationProfileId {
+    }
+
+    /**
+     * The profile is unknown because it is a profile unknown to this version of the SDK.
+     */
+    public static final int PROFILE_UNKNOWN = 0;
+
+    /** The profile is defined by an app. */
+    public static final int PROFILE_APP_DEFINED = 1;
+
+    /**
+     * A system-defined profile which verifies that the attesting environment can create an
+     * attestation with the same root certificate as the verifying device with a matching
+     * attestation challenge.
+     *
+     * This profile is intended to be used only for testing.
+     */
+    public static final int PROFILE_SELF_TRUSTED = 2;
+
+    /**
+     * A system-defined profile which verifies that the attesting environment environment is similar
+     * to the current device in terms of security model and security configuration. This category is
+     * fairly broad and most securely configured Android devices should qualify, along with a
+     * variety of non-Android devices.
+     */
+    public static final int PROFILE_PEER_DEVICE = 3;
+
+    /** @hide */
+    @IntDef(
+            prefix = {"TYPE_"},
+            value = {
+                    TYPE_UNKNOWN,
+                    TYPE_APP_DEFINED,
+                    TYPE_PUBLIC_KEY,
+                    TYPE_CHALLENGE,
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface LocalBindingType {
+    }
+
+    /**
+     * The type of the local binding data is unknown because it is a type unknown to this version of
+     * the SDK.
+     */
+    public static final int TYPE_UNKNOWN = 0;
+
+    /**
+     * A local binding type for app-defined profiles which use local binding data which does not
+     * match any of the existing system-defined types.
+     */
+    public static final int TYPE_APP_DEFINED = 1;
+
+    /**
+     * A local binding type where the attestation is bound to a public key negotiated and
+     * authenticated to a public key.
+     *
+     * <p>When using this type, the {@code requirements} bundle contains values for:
+     * <ul>
+     *   <li>{@link #PARAM_PUBLIC_KEY}
+     *   <li>{@link #PARAM_ID}: identifying the remote environment, optional
+     * </ul>
+     */
+    public static final int TYPE_PUBLIC_KEY = 2;
+
+    /**
+     * A local binding type where the attestation is bound to a challenge.
+     *
+     * <p>When using this type, the {@code requirements} bundle contains values for:
+     * <ul>
+     *   <li>{@link #PARAM_CHALLENGE}: containing the challenge
+     * </ul>
+     */
+    public static final int TYPE_CHALLENGE = 3;
+
+    /** @hide */
+    @IntDef(
+            prefix = {"RESULT_"},
+            value = {
+                    RESULT_UNKNOWN,
+                    RESULT_SUCCESS,
+                    RESULT_FAILURE,
+            })
+    @Retention(RetentionPolicy.SOURCE)
+    @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
+    public @interface VerificationResult {
+    }
+
+    /** The result of the verification is unknown because it has a value unknown to this SDK. */
+    public static final int RESULT_UNKNOWN = 0;
+
+    /** The result of the verification was successful. */
+    public static final int RESULT_SUCCESS = 1;
+
+    /**
+     * The result of the attestation verification was failure. The attestation could not be
+     * verified.
+     */
+    public static final int RESULT_FAILURE = 2;
+
+    /**
+     * Requirements bundle parameter key for a public key, a byte array.
+     *
+     * <p>This should contain the encoded key bytes according to the ASN.1 type
+     * {@code SubjectPublicKeyInfo} defined in the X.509 standard, the same as a call to {@link
+     * java.security.spec.X509EncodedKeySpec#getEncoded()} would produce.
+     *
+     * @see Bundle#putByteArray(String, byte[])
+     */
+    public static final String PARAM_PUBLIC_KEY = "localbinding.public_key";
+
+    /** Requirements bundle parameter key for an ID, String. */
+    public static final String PARAM_ID = "localbinding.id";
+
+    /** Requirements bundle parameter for a challenge. */
+    public static final String PARAM_CHALLENGE = "localbinding.challenge";
+}
diff --git a/core/java/android/security/attestationverification/AttestationVerificationService.java b/core/java/android/security/attestationverification/AttestationVerificationService.java
new file mode 100644
index 0000000..26c3051
--- /dev/null
+++ b/core/java/android/security/attestationverification/AttestationVerificationService.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2021 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 android.security.attestationverification;
+
+import android.annotation.CheckResult;
+import android.annotation.NonNull;
+import android.app.Service;
+import android.os.Bundle;
+import android.security.attestationverification.AttestationVerificationManager.VerificationResult;
+
+/**
+ * A verifier which can be implemented by apps to verify an attestation (as described in {@link
+ * AttestationVerificationManager}).
+ *
+ * In the manifest for this service, specify the profile and local binding type this verifier
+ * supports. Create a new service for each combination of profile & local binding type that your app
+ * supports. Each service must declare an {@code intent-filter} action of {@link #SERVICE_INTERFACE}
+ * and permission of {@link android.Manifest.permission#BIND_ATTESTATION_VERIFICATION_SERVICE}.
+ *
+ * <p>Example:
+ * {@code
+ * <pre>
+ * <service android:name=".MyAttestationVerificationService"
+ *          android:permission="android.permission.BIND_ATTESTATION_VERIFICATION_SERVICE"
+ *          android:exported="true">
+ *   <intent-filter>
+ *     <action
+ *         android:name="android.security.attestationverification.AttestationVerificationService" />
+ *   </intent-filter>
+ *   <meta-data android:name="android.security.attestationverification.PROFILE_ID"
+ *              android:value="PROFILE_PLACEHOLDER_0" />
+ *   <meta-data android:name="android.security.attestationverification.LOCAL_BINDING_TYPE"
+ *              android:value="TYPE_PLACEHOLDER_0" />
+ * </service>
+ * </pre>
+ * }
+ *
+ * <p>For app-defined profiles, an example of the {@code <meta-data>}:
+ * {@code
+ * <pre>
+ *   <meta-data android:name="android.security.attestation.PROFILE_PACKAGE_NAME"
+ *              android:value="com.example" />
+ *   <meta-data android:name="android.security.attestation.PROFILE_NAME"
+ *              android:value="com.example.profile.PROFILE_FOO" />
+ * </pre>
+ * }
+ *
+ * @hide
+ */
+public abstract class AttestationVerificationService extends Service {
+
+    /**
+     * An intent action for a service to be bound and act as an attestation verifier.
+     *
+     * <p>The app will be kept alive for a short duration between verification calls after which
+     * the system will unbind from this service making the app eligible for cleanup.
+     *
+     * <p>The service must also require permission
+     * {@link android.Manifest.permission#BIND_ATTESTATION_VERIFICATION_SERVICE}.
+     */
+    public static final String SERVICE_INTERFACE =
+            "android.security.attestationverification.AttestationVerificationService";
+
+    /**
+     * Verifies that {@code attestation} attests that the device identified by the local binding
+     * data in {@code requirements} meets the minimum requirements of this verifier for this
+     * verifier's profile.
+     *
+     * <p>Called by the system to verify an attestation.
+     *
+     * <p>The data passed into this method comes directly from apps and should be treated as
+     * potentially dangerous user input.
+     *
+     * @param requirements a {@link Bundle} containing locally-known data which must match {@code
+     *                     attestation}
+     * @param attestation  the attestation to verify
+     * @return whether the verification passed
+     * @see AttestationVerificationManager#verifyAttestation(AttestationProfile, int, Bundle,
+     * byte[], java.util.concurrent.Executor, java.util.function.BiConsumer)
+     */
+    @CheckResult
+    @VerificationResult
+    public abstract int onVerifyPeerDeviceAttestation(
+            @NonNull Bundle requirements,
+            @NonNull byte[] attestation);
+}
diff --git a/core/java/android/security/attestationverification/IAttestationVerificationManagerService.aidl b/core/java/android/security/attestationverification/IAttestationVerificationManagerService.aidl
new file mode 100644
index 0000000..2fb328c
--- /dev/null
+++ b/core/java/android/security/attestationverification/IAttestationVerificationManagerService.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2021 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 android.security.attestationverification;
+
+import android.os.Bundle;
+import android.os.ParcelDuration;
+import android.security.attestationverification.AttestationProfile;
+import android.security.attestationverification.VerificationToken;
+import com.android.internal.infra.AndroidFuture;
+
+
+/**
+ * Binder interface to communicate with AttestationVerificationManagerService.
+ * @hide
+ */
+oneway interface IAttestationVerificationManagerService {
+
+    void verifyAttestation(
+            in AttestationProfile profile,
+            in int localBindingType,
+            in Bundle requirements,
+            in byte[] attestation,
+            in AndroidFuture resultCallback);
+
+    void verifyToken(
+            in VerificationToken token,
+            in ParcelDuration maximumTokenAge,
+            in AndroidFuture resultCallback);
+}
diff --git a/core/java/android/security/attestationverification/IAttestationVerificationService.aidl b/core/java/android/security/attestationverification/IAttestationVerificationService.aidl
new file mode 100644
index 0000000..082ad32
--- /dev/null
+++ b/core/java/android/security/attestationverification/IAttestationVerificationService.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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 android.security.attestationverification;
+
+import android.os.Bundle;
+import com.android.internal.infra.AndroidFuture;
+
+
+/**
+ * Binder interface for the system server to communicate with app implementations of
+ * AttestationVerificationService.
+ * @hide
+ */
+oneway interface IAttestationVerificationService {
+    void onVerifyAttestation(
+        in Bundle requirements,
+        in byte[] attestation,
+        in AndroidFuture callback);
+}
diff --git a/core/java/android/window/TaskFragmentAppearedInfo.aidl b/core/java/android/security/attestationverification/IVerificationResult.aidl
similarity index 61%
copy from core/java/android/window/TaskFragmentAppearedInfo.aidl
copy to core/java/android/security/attestationverification/IVerificationResult.aidl
index 3729c09..f61c456 100644
--- a/core/java/android/window/TaskFragmentAppearedInfo.aidl
+++ b/core/java/android/security/attestationverification/IVerificationResult.aidl
@@ -14,10 +14,19 @@
  * limitations under the License.
  */
 
-package android.window;
+package android.security.attestationverification;
+
+import android.security.attestationverification.VerificationToken;
+
 
 /**
- * Data object for the TaskFragment info provided when a TaskFragment is presented to an organizer.
- * @hide
+ * The result of an attestation verification.
+ *
+ * {@hide}
  */
-parcelable TaskFragmentAppearedInfo;
+parcelable IVerificationResult {
+    /** The result code corresponding to @VerificationResult. */
+    int resultCode;
+    /** The token for the verification or null. */
+    VerificationToken token;
+}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt b/core/java/android/security/attestationverification/VerificationToken.aidl
similarity index 84%
copy from packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
copy to core/java/android/security/attestationverification/VerificationToken.aidl
index bacc66b..666a8b0 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
+++ b/core/java/android/security/attestationverification/VerificationToken.aidl
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.flags
+package android.security.attestationverification;
 
-interface FlagWriter {
-    fun setEnabled(key: Int, value: Boolean) {}
-}
\ No newline at end of file
+/**
+ * {@hide}
+ */
+parcelable VerificationToken;
diff --git a/core/java/android/security/attestationverification/VerificationToken.java b/core/java/android/security/attestationverification/VerificationToken.java
new file mode 100644
index 0000000..ae26823
--- /dev/null
+++ b/core/java/android/security/attestationverification/VerificationToken.java
@@ -0,0 +1,523 @@
+/*
+ * Copyright (C) 2021 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 android.security.attestationverification;
+
+import android.annotation.NonNull;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.security.attestationverification.AttestationVerificationManager.LocalBindingType;
+import android.security.attestationverification.AttestationVerificationManager.VerificationResult;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForInstant;
+
+import java.time.Duration;
+import java.util.concurrent.Executor;
+import java.util.function.BiConsumer;
+
+/**
+ * Token representing the result of an attestation verification, which can be passed to other parts
+ * of the OS or other apps as proof of the verification.
+ *
+ * Tokens are only valid within the same UID (which means within a single app unless the deprecated
+ * android:sharedUserId manifest value is used).
+ *
+ * @hide
+ * @see Bundle#putParcelable(String, Parcelable)
+ */
+@DataClass(
+        genConstructor = false,
+        genHiddenBuilder = true
+)
+public final class VerificationToken implements Parcelable {
+
+    /**
+     * The attestation profile which was used to perform the verification.
+     * @hide
+     */
+    @NonNull
+    private final AttestationProfile mAttestationProfile;
+
+    /**
+     * The local binding type of the local binding data used to perform the verification.
+     * @hide
+     */
+    @LocalBindingType
+    private final int mLocalBindingType;
+
+    /**
+     * The requirements used to perform the verification.
+     * @hide
+     */
+    @NonNull
+    private final Bundle mRequirements;
+
+    /**
+     * The result of the {@link AttestationVerificationManager#verifyAttestation(int, int, Bundle,
+     * byte[], Executor, BiConsumer)} call. This value is kept hidden to prevent token holders from
+     * accidentally reading this value without calling {@code verifyToken}. Do <b>not</b> use this
+     * value directly; call {@link AttestationVerificationManager#verifyToken(VerificationToken,
+     * Duration)} to verify a valid token and it will return this value.
+     *
+     * If the token is valid, this value is returned directly by {#verifyToken}.
+     *
+     * @hide
+     */
+    @VerificationResult
+    private final int mVerificationResult;
+
+    /**
+     * Time when the token was generated, set by the system.
+     */
+    @NonNull
+    @DataClass.ParcelWith(ForInstant.class)
+    private final java.time.Instant mVerificationTime;
+
+    /**
+     * A Hash-based message authentication code used to verify the contents and authenticity of the
+     * rest of the token. The hash is created using a secret key known only to the system server.
+     * When verifying the token, the system re-hashes the token and verifies the generated HMAC is
+     * the same.
+     *
+     * @hide
+     */
+    @NonNull
+    private final byte[] mHmac;
+
+    /**
+     * The UID of the process which called {@code verifyAttestation} to create the token, as
+     * returned by {@link Binder#getCallingUid()}. Calls to {@code verifyToken} will fail if the UID
+     * of calling process does not match this value. This ensures that tokens cannot be shared
+     * between UIDs.
+     *
+     * @hide
+     */
+    private int mUid;
+
+
+    // Code below generated by codegen v1.0.23.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/security/attestationverification/VerificationToken.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    /* package-private */ VerificationToken(
+            @NonNull AttestationProfile attestationProfile,
+            @LocalBindingType int localBindingType,
+            @NonNull Bundle requirements,
+            @VerificationResult int verificationResult,
+            @NonNull java.time.Instant verificationTime,
+            @NonNull byte[] hmac,
+            int uid) {
+        this.mAttestationProfile = attestationProfile;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAttestationProfile);
+        this.mLocalBindingType = localBindingType;
+        com.android.internal.util.AnnotationValidations.validate(
+                LocalBindingType.class, null, mLocalBindingType);
+        this.mRequirements = requirements;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mRequirements);
+        this.mVerificationResult = verificationResult;
+        com.android.internal.util.AnnotationValidations.validate(
+                VerificationResult.class, null, mVerificationResult);
+        this.mVerificationTime = verificationTime;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mVerificationTime);
+        this.mHmac = hmac;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mHmac);
+        this.mUid = uid;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * The attestation profile which was used to perform the verification.
+     */
+    @DataClass.Generated.Member
+    public @NonNull AttestationProfile getAttestationProfile() {
+        return mAttestationProfile;
+    }
+
+    /**
+     * The local binding type of the local binding data used to perform the verification.
+     */
+    @DataClass.Generated.Member
+    public @LocalBindingType int getLocalBindingType() {
+        return mLocalBindingType;
+    }
+
+    /**
+     * The requirements used to perform the verification.
+     */
+    @DataClass.Generated.Member
+    public @NonNull Bundle getRequirements() {
+        return mRequirements;
+    }
+
+    /**
+     * The result of the {@link AttestationVerificationManager#verifyAttestation(int, int, Bundle,
+     * byte[], Executor, BiConsumer)} call. This value is kept hidden to prevent token holders from
+     * accidentally reading this value without calling {@code verifyToken}. Do <b>not</b> use this
+     * value directly; call {@link AttestationVerificationManager#verifyToken(VerificationToken,
+     * Duration)} to verify a valid token and it will return this value.
+     *
+     * If the token is valid, this value is returned directly by {#verifyToken}.
+     *
+     * @hide
+     */
+    @DataClass.Generated.Member
+    public @VerificationResult int getVerificationResult() {
+        return mVerificationResult;
+    }
+
+    /**
+     * Time when the token was generated, set by the system.
+     */
+    @DataClass.Generated.Member
+    public @NonNull java.time.Instant getVerificationTime() {
+        return mVerificationTime;
+    }
+
+    /**
+     * A Hash-based message authentication code used to verify the contents and authenticity of the
+     * rest of the token. The hash is created using a secret key known only to the system server.
+     * When verifying the token, the system re-hashes the token and verifies the generated HMAC is
+     * the same.
+     *
+     * @hide
+     */
+    @DataClass.Generated.Member
+    public @NonNull byte[] getHmac() {
+        return mHmac;
+    }
+
+    /**
+     * The UID of the process which called {@code verifyAttestation} to create the token, as
+     * returned by {@link Binder#getCallingUid()}. Calls to {@code verifyToken} will fail if the UID
+     * of calling process does not match this value. This ensures that tokens cannot be shared
+     * between UIDs.
+     *
+     * @hide
+     */
+    @DataClass.Generated.Member
+    public int getUid() {
+        return mUid;
+    }
+
+    @DataClass.Generated.Member
+    static Parcelling<java.time.Instant> sParcellingForVerificationTime =
+            Parcelling.Cache.get(
+                    ForInstant.class);
+    static {
+        if (sParcellingForVerificationTime == null) {
+            sParcellingForVerificationTime = Parcelling.Cache.put(
+                    new ForInstant());
+        }
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeTypedObject(mAttestationProfile, flags);
+        dest.writeInt(mLocalBindingType);
+        dest.writeBundle(mRequirements);
+        dest.writeInt(mVerificationResult);
+        sParcellingForVerificationTime.parcel(mVerificationTime, dest, flags);
+        dest.writeByteArray(mHmac);
+        dest.writeInt(mUid);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ VerificationToken(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        AttestationProfile attestationProfile = (AttestationProfile) in.readTypedObject(AttestationProfile.CREATOR);
+        int localBindingType = in.readInt();
+        Bundle requirements = in.readBundle();
+        int verificationResult = in.readInt();
+        java.time.Instant verificationTime = sParcellingForVerificationTime.unparcel(in);
+        byte[] hmac = in.createByteArray();
+        int uid = in.readInt();
+
+        this.mAttestationProfile = attestationProfile;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAttestationProfile);
+        this.mLocalBindingType = localBindingType;
+        com.android.internal.util.AnnotationValidations.validate(
+                LocalBindingType.class, null, mLocalBindingType);
+        this.mRequirements = requirements;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mRequirements);
+        this.mVerificationResult = verificationResult;
+        com.android.internal.util.AnnotationValidations.validate(
+                VerificationResult.class, null, mVerificationResult);
+        this.mVerificationTime = verificationTime;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mVerificationTime);
+        this.mHmac = hmac;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mHmac);
+        this.mUid = uid;
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<VerificationToken> CREATOR
+            = new Parcelable.Creator<VerificationToken>() {
+        @Override
+        public VerificationToken[] newArray(int size) {
+            return new VerificationToken[size];
+        }
+
+        @Override
+        public VerificationToken createFromParcel(@NonNull android.os.Parcel in) {
+            return new VerificationToken(in);
+        }
+    };
+
+    /**
+     * A builder for {@link VerificationToken}
+     * @hide
+     */
+    @SuppressWarnings("WeakerAccess")
+    @DataClass.Generated.Member
+    public static final class Builder {
+
+        private @NonNull AttestationProfile mAttestationProfile;
+        private @LocalBindingType int mLocalBindingType;
+        private @NonNull Bundle mRequirements;
+        private @VerificationResult int mVerificationResult;
+        private @NonNull java.time.Instant mVerificationTime;
+        private @NonNull byte[] mHmac;
+        private int mUid;
+
+        private long mBuilderFieldsSet = 0L;
+
+        /**
+         * Creates a new Builder.
+         *
+         * @param attestationProfile
+         *   The attestation profile which was used to perform the verification.
+         * @param localBindingType
+         *   The local binding type of the local binding data used to perform the verification.
+         * @param requirements
+         *   The requirements used to perform the verification.
+         * @param verificationResult
+         *   The result of the {@link AttestationVerificationManager#verifyAttestation(int, int, Bundle,
+         *   byte[], Executor, BiConsumer)} call. This value is kept hidden to prevent token holders from
+         *   accidentally reading this value without calling {@code verifyToken}. Do <b>not</b> use this
+         *   value directly; call {@link AttestationVerificationManager#verifyToken(VerificationToken,
+         *   Duration)} to verify a valid token and it will return this value.
+         *
+         *   If the token is valid, this value is returned directly by {#verifyToken}.
+         * @param verificationTime
+         *   Time when the token was generated, set by the system.
+         * @param hmac
+         *   A Hash-based message authentication code used to verify the contents and authenticity of the
+         *   rest of the token. The hash is created using a secret key known only to the system server.
+         *   When verifying the token, the system re-hashes the token and verifies the generated HMAC is
+         *   the same.
+         * @param uid
+         *   The UID of the process which called {@code verifyAttestation} to create the token, as
+         *   returned by {@link Binder#getCallingUid()}. Calls to {@code verifyToken} will fail if the UID
+         *   of calling process does not match this value. This ensures that tokens cannot be shared
+         *   between UIDs.
+         */
+        public Builder(
+                @NonNull AttestationProfile attestationProfile,
+                @LocalBindingType int localBindingType,
+                @NonNull Bundle requirements,
+                @VerificationResult int verificationResult,
+                @NonNull java.time.Instant verificationTime,
+                @NonNull byte[] hmac,
+                int uid) {
+            mAttestationProfile = attestationProfile;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mAttestationProfile);
+            mLocalBindingType = localBindingType;
+            com.android.internal.util.AnnotationValidations.validate(
+                    LocalBindingType.class, null, mLocalBindingType);
+            mRequirements = requirements;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mRequirements);
+            mVerificationResult = verificationResult;
+            com.android.internal.util.AnnotationValidations.validate(
+                    VerificationResult.class, null, mVerificationResult);
+            mVerificationTime = verificationTime;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mVerificationTime);
+            mHmac = hmac;
+            com.android.internal.util.AnnotationValidations.validate(
+                    NonNull.class, null, mHmac);
+            mUid = uid;
+        }
+
+        /**
+         * The attestation profile which was used to perform the verification.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setAttestationProfile(@NonNull AttestationProfile value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x1;
+            mAttestationProfile = value;
+            return this;
+        }
+
+        /**
+         * The local binding type of the local binding data used to perform the verification.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setLocalBindingType(@LocalBindingType int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x2;
+            mLocalBindingType = value;
+            return this;
+        }
+
+        /**
+         * The requirements used to perform the verification.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setRequirements(@NonNull Bundle value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x4;
+            mRequirements = value;
+            return this;
+        }
+
+        /**
+         * The result of the {@link AttestationVerificationManager#verifyAttestation(int, int, Bundle,
+         * byte[], Executor, BiConsumer)} call. This value is kept hidden to prevent token holders from
+         * accidentally reading this value without calling {@code verifyToken}. Do <b>not</b> use this
+         * value directly; call {@link AttestationVerificationManager#verifyToken(VerificationToken,
+         * Duration)} to verify a valid token and it will return this value.
+         *
+         * If the token is valid, this value is returned directly by {#verifyToken}.
+         *
+         * @hide
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setVerificationResult(@VerificationResult int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x8;
+            mVerificationResult = value;
+            return this;
+        }
+
+        /**
+         * Time when the token was generated, set by the system.
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setVerificationTime(@NonNull java.time.Instant value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x10;
+            mVerificationTime = value;
+            return this;
+        }
+
+        /**
+         * A Hash-based message authentication code used to verify the contents and authenticity of the
+         * rest of the token. The hash is created using a secret key known only to the system server.
+         * When verifying the token, the system re-hashes the token and verifies the generated HMAC is
+         * the same.
+         *
+         * @hide
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setHmac(@NonNull byte... value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x20;
+            mHmac = value;
+            return this;
+        }
+
+        /**
+         * The UID of the process which called {@code verifyAttestation} to create the token, as
+         * returned by {@link Binder#getCallingUid()}. Calls to {@code verifyToken} will fail if the UID
+         * of calling process does not match this value. This ensures that tokens cannot be shared
+         * between UIDs.
+         *
+         * @hide
+         */
+        @DataClass.Generated.Member
+        public @NonNull Builder setUid(int value) {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x40;
+            mUid = value;
+            return this;
+        }
+
+        /** Builds the instance. This builder should not be touched after calling this! */
+        public @NonNull VerificationToken build() {
+            checkNotUsed();
+            mBuilderFieldsSet |= 0x80; // Mark builder used
+
+            VerificationToken o = new VerificationToken(
+                    mAttestationProfile,
+                    mLocalBindingType,
+                    mRequirements,
+                    mVerificationResult,
+                    mVerificationTime,
+                    mHmac,
+                    mUid);
+            return o;
+        }
+
+        private void checkNotUsed() {
+            if ((mBuilderFieldsSet & 0x80) != 0) {
+                throw new IllegalStateException(
+                        "This Builder should not be reused. Use a new Builder instance instead");
+            }
+        }
+    }
+
+    @DataClass.Generated(
+            time = 1633629747234L,
+            codegenVersion = "1.0.23",
+            sourceFile = "frameworks/base/core/java/android/security/attestationverification/VerificationToken.java",
+            inputSignatures = "private final @android.annotation.NonNull android.security.attestationverification.AttestationProfile mAttestationProfile\nprivate final @android.security.attestationverification.AttestationVerificationManager.LocalBindingType int mLocalBindingType\nprivate final @android.annotation.NonNull android.os.Bundle mRequirements\nprivate final  @android.security.attestationverification.AttestationVerificationManager.VerificationResult int mVerificationResult\nprivate final @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInstant.class) java.time.Instant mVerificationTime\nprivate final @android.annotation.NonNull byte[] mHmac\nprivate  int mUid\nclass VerificationToken extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genHiddenBuilder=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/security/attestationverification/package.html b/core/java/android/security/attestationverification/package.html
new file mode 100644
index 0000000..783d0a1
--- /dev/null
+++ b/core/java/android/security/attestationverification/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body>
diff --git a/core/java/android/service/wallpaper/EngineWindowPage.java b/core/java/android/service/wallpaper/EngineWindowPage.java
index 5ed0ad6..006e3cd 100644
--- a/core/java/android/service/wallpaper/EngineWindowPage.java
+++ b/core/java/android/service/wallpaper/EngineWindowPage.java
@@ -24,7 +24,6 @@
 
 import java.util.Map;
 import java.util.Set;
-import java.util.function.Consumer;
 
 /**
  * This class represents a page of a launcher page used by the wallpaper
@@ -84,11 +83,6 @@
         return mCallbackAreas;
     }
 
-    /** run operations on this page */
-    public synchronized void execSync(Consumer<EngineWindowPage> run) {
-        run.accept(this);
-    }
-
     /** nullify the area color */
     public void removeColor(RectF colorArea) {
         mRectFColors.remove(colorArea);
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index c77399f..7b8410b 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -1490,7 +1490,7 @@
             //below is the default implementation
             if (xOffset % xOffsetStep > MIN_PAGE_ALLOWED_MARGIN
                     || !mSurfaceHolder.getSurface().isValid()) return;
-            int xPage;
+            int xCurrentPage;
             int xPages;
             if (!validStep(xOffsetStep)) {
                 if (DEBUG) {
@@ -1498,30 +1498,34 @@
                 }
                 xOffset = 0;
                 xOffsetStep = 1;
-                xPage = 0;
+                xCurrentPage = 0;
                 xPages = 1;
             } else {
                 xPages = Math.round(1 / xOffsetStep) + 1;
                 xOffsetStep = (float) 1 / (float) xPages;
                 float shrink = (float) (xPages - 1) / (float) xPages;
                 xOffset *= shrink;
-                xPage = Math.round(xOffset / xOffsetStep);
+                xCurrentPage = Math.round(xOffset / xOffsetStep);
             }
             if (DEBUG) {
-                Log.d(TAG, "xPages " + xPages + " xPage " + xPage);
+                Log.d(TAG, "xPages " + xPages + " xPage " + xCurrentPage);
                 Log.d(TAG, "xOffsetStep " + xOffsetStep + " xOffset " + xOffset);
             }
-            EngineWindowPage current;
-            synchronized (mLock) {
+
+            float finalXOffsetStep = xOffsetStep;
+            float finalXOffset = xOffset;
+            mHandler.post(() -> {
+                int xPage = xCurrentPage;
+                EngineWindowPage current;
                 if (mWindowPages.length == 0 || (mWindowPages.length != xPages)) {
                     mWindowPages = new EngineWindowPage[xPages];
-                    initWindowPages(mWindowPages, xOffsetStep);
+                    initWindowPages(mWindowPages, finalXOffsetStep);
                 }
                 if (mLocalColorsToAdd.size() != 0) {
                     for (RectF colorArea : mLocalColorsToAdd) {
                         if (!isValid(colorArea)) continue;
                         mLocalColorAreas.add(colorArea);
-                        int colorPage = getRectFPage(colorArea, xOffsetStep);
+                        int colorPage = getRectFPage(colorArea, finalXOffsetStep);
                         EngineWindowPage currentPage = mWindowPages[colorPage];
                         if (currentPage == null) {
                             currentPage = new EngineWindowPage();
@@ -1539,7 +1543,8 @@
                         Log.e(TAG, "error xPage >= mWindowPages.length page: " + xPage);
                         Log.e(TAG, "error on page " + xPage + " out of " + xPages);
                         Log.e(TAG,
-                                "error on xOffsetStep " + xOffsetStep + " xOffset " + xOffset);
+                                "error on xOffsetStep " + finalXOffsetStep
+                                        + " xOffset " + finalXOffset);
                     }
                     xPage = mWindowPages.length - 1;
                 }
@@ -1547,13 +1552,14 @@
                 if (current == null) {
                     if (DEBUG) Log.d(TAG, "making page " + xPage + " out of " + xPages);
                     if (DEBUG) {
-                        Log.d(TAG, "xOffsetStep " + xOffsetStep + " xOffset " + xOffset);
+                        Log.d(TAG, "xOffsetStep " + finalXOffsetStep + " xOffset "
+                                + finalXOffset);
                     }
                     current = new EngineWindowPage();
                     mWindowPages[xPage] = current;
                 }
-            }
-            updatePage(current, xPage, xPages, xOffsetStep);
+                updatePage(current, xPage, xPages, finalXOffsetStep);
+            });
         }
 
         private void initWindowPages(EngineWindowPage[] windowPages, float step) {
@@ -1603,10 +1609,8 @@
                 if (DEBUG) Log.d(TAG, "result of pixel copy is " + res);
                 if (res != PixelCopy.SUCCESS) {
                     Bitmap lastBitmap = currentPage.getBitmap();
-                    currentPage.execSync((p) -> {
-                        // assign the last bitmap taken for now
-                        p.setBitmap(mLastScreenshot);
-                    });
+                    // assign the last bitmap taken for now
+                    currentPage.setBitmap(mLastScreenshot);
                     Bitmap lastScreenshot = mLastScreenshot;
                     if (lastScreenshot != null && !lastScreenshot.isRecycled()
                             && !Objects.equals(lastBitmap, lastScreenshot)) {
@@ -1615,10 +1619,8 @@
                 } else {
                     mLastScreenshot = finalScreenShot;
                     // going to hold this lock for a while
-                    currentPage.execSync((p) -> {
-                        p.setBitmap(finalScreenShot);
-                        p.setLastUpdateTime(current);
-                    });
+                    currentPage.setBitmap(finalScreenShot);
+                    currentPage.setLastUpdateTime(current);
                     updatePageColors(currentPage, pageIndx, numPages, xOffsetStep);
                 }
             }, mHandler);
@@ -1698,16 +1700,14 @@
         private void resetWindowPages() {
             if (supportsLocalColorExtraction()) return;
             mLastWindowPage = -1;
-            synchronized (mLock) {
+            mHandler.post(() -> {
                 for (int i = 0; i < mWindowPages.length; i++) {
                     EngineWindowPage page = mWindowPages[i];
                     if (page != null) {
-                        page.execSync((p) -> {
-                            p.setLastUpdateTime(0L);
-                        });
+                        page.setLastUpdateTime(0L);
                     }
                 }
-            }
+            });
         }
 
         private int getRectFPage(RectF area, float step) {
@@ -1730,10 +1730,10 @@
             if (DEBUG) {
                 Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions);
             }
-            float step = mPendingXOffsetStep;
 
             List<WallpaperColors> colors = getLocalWallpaperColors(regions);
-            synchronized (mLock) {
+            mHandler.post(() -> {
+                float step = mPendingXOffsetStep;
                 if (!validStep(step)) {
                     step = 0;
                 }
@@ -1749,26 +1749,25 @@
                         page.addArea(area);
                         WallpaperColors color = colors.get(i);
                         if (color != null && !color.equals(page.getColors(area))) {
-                            page.execSync(p -> {
-                                p.addWallpaperColors(area, color);
-                            });
+                            page.addWallpaperColors(area, color);
                         }
                     } else {
                         mLocalColorsToAdd.add(area);
                     }
                 }
-            }
-
-            for (int i = 0; i < colors.size() && colors.get(i) != null; i++) {
-                try {
-                    mConnection.onLocalWallpaperColorsChanged(regions.get(i), colors.get(i),
-                            mDisplayContext.getDisplayId());
-                } catch (RemoteException e) {
-                    Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e);
-                    return;
+                for (int i = 0; i < colors.size() && colors.get(i) != null; i++) {
+                    try {
+                        mConnection.onLocalWallpaperColorsChanged(regions.get(i), colors.get(i),
+                                mDisplayContext.getDisplayId());
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e);
+                        return;
+                    }
                 }
-            }
-            processLocalColors(mPendingXOffset, mPendingYOffset);
+                processLocalColors(mPendingXOffset, mPendingYOffset);
+            });
+
+
         }
 
         /**
@@ -1778,7 +1777,7 @@
          */
         public void removeLocalColorsAreas(@NonNull List<RectF> regions) {
             if (supportsLocalColorExtraction()) return;
-            synchronized (mLock) {
+            mHandler.post(() -> {
                 float step = mPendingXOffsetStep;
                 mLocalColorsToAdd.removeAll(regions);
                 mLocalColorAreas.removeAll(regions);
@@ -1792,12 +1791,10 @@
                     // no page should be null
                     EngineWindowPage page = mWindowPages[pageInx];
                     if (page != null) {
-                        page.execSync(p -> {
-                            p.removeArea(area);
-                        });
+                        page.removeArea(area);
                     }
                 }
-            }
+            });
         }
 
         private @NonNull List<WallpaperColors> getLocalWallpaperColors(@NonNull List<RectF> areas) {
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 505f400..da3e9b6 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -82,7 +82,9 @@
     /** @hide */
     @IntDef(prefix = { "HYPHENATION_FREQUENCY_" }, value = {
             HYPHENATION_FREQUENCY_NORMAL,
+            HYPHENATION_FREQUENCY_NORMAL_FAST,
             HYPHENATION_FREQUENCY_FULL,
+            HYPHENATION_FREQUENCY_FULL_FAST,
             HYPHENATION_FREQUENCY_NONE
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -95,21 +97,40 @@
      * layout and there is otherwise no valid break. Soft hyphens are ignored and will not be used
      * as suggestions for potential line breaks.
      */
-    public static final int HYPHENATION_FREQUENCY_NONE = LineBreaker.HYPHENATION_FREQUENCY_NONE;
+    public static final int HYPHENATION_FREQUENCY_NONE = 0;
 
     /**
      * Value for hyphenation frequency indicating a light amount of automatic hyphenation, which
      * is a conservative default. Useful for informal cases, such as short sentences or chat
      * messages.
      */
-    public static final int HYPHENATION_FREQUENCY_NORMAL = LineBreaker.HYPHENATION_FREQUENCY_NORMAL;
+    public static final int HYPHENATION_FREQUENCY_NORMAL = 1;
 
     /**
      * Value for hyphenation frequency indicating the full amount of automatic hyphenation, typical
      * in typography. Useful for running text and where it's important to put the maximum amount of
      * text in a screen with limited space.
      */
-    public static final int HYPHENATION_FREQUENCY_FULL = LineBreaker.HYPHENATION_FREQUENCY_FULL;
+    public static final int HYPHENATION_FREQUENCY_FULL = 2;
+
+    /**
+     * Value for hyphenation frequency indicating a light amount of automatic hyphenation with
+     * using faster algorithm.
+     *
+     * This option is useful for informal cases, such as short sentences or chat messages. To make
+     * text rendering faster with hyphenation, this algorithm ignores some hyphen character related
+     * typographic features, e.g. kerning.
+     */
+    public static final int HYPHENATION_FREQUENCY_NORMAL_FAST = 3;
+    /**
+     * Value for hyphenation frequency indicating the full amount of automatic hyphenation with
+     * using faster algorithm.
+     *
+     * This option is useful for running text and where it's important to put the maximum amount of
+     * text in a screen with limited space. To make text rendering faster with hyphenation, this
+     * algorithm ignores some hyphen character related typographic features, e.g. kerning.
+     */
+    public static final int HYPHENATION_FREQUENCY_FULL_FAST = 4;
 
     private static final ParagraphStyle[] NO_PARA_SPANS =
         ArrayUtils.emptyArray(ParagraphStyle.class);
diff --git a/core/java/android/text/MeasuredParagraph.java b/core/java/android/text/MeasuredParagraph.java
index 7e41878..6a3c618 100644
--- a/core/java/android/text/MeasuredParagraph.java
+++ b/core/java/android/text/MeasuredParagraph.java
@@ -377,7 +377,7 @@
      * @param start the inclusive start offset of the target region in the text
      * @param end the exclusive end offset of the target region in the text
      * @param textDir the text direction
-     * @param computeHyphenation true if need to compute hyphenation, otherwise false
+     * @param hyphenationMode a hyphenation mode
      * @param computeLayout true if need to compute full layout, otherwise false.
      * @param hint pass if you already have measured paragraph.
      * @param recycle pass existing MeasuredParagraph if you want to recycle it.
@@ -390,7 +390,7 @@
             @IntRange(from = 0) int start,
             @IntRange(from = 0) int end,
             @NonNull TextDirectionHeuristic textDir,
-            boolean computeHyphenation,
+            int hyphenationMode,
             boolean computeLayout,
             @Nullable MeasuredParagraph hint,
             @Nullable MeasuredParagraph recycle) {
@@ -399,7 +399,7 @@
         final MeasuredText.Builder builder;
         if (hint == null) {
             builder = new MeasuredText.Builder(mt.mCopiedBuffer)
-                    .setComputeHyphenation(computeHyphenation)
+                    .setComputeHyphenation(hyphenationMode)
                     .setComputeLayout(computeLayout);
         } else {
             builder = new MeasuredText.Builder(hint.mMeasuredText);
diff --git a/core/java/android/text/PrecomputedText.java b/core/java/android/text/PrecomputedText.java
index 08741d6..152570f 100644
--- a/core/java/android/text/PrecomputedText.java
+++ b/core/java/android/text/PrecomputedText.java
@@ -22,6 +22,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.Rect;
+import android.graphics.text.MeasuredText;
 import android.text.style.MetricAffectingSpan;
 
 import com.android.internal.util.Preconditions;
@@ -395,17 +396,30 @@
         return new PrecomputedText(text, 0, text.length(), params, paraInfo);
     }
 
+    private static boolean isFastHyphenation(int frequency) {
+        return frequency == Layout.HYPHENATION_FREQUENCY_FULL_FAST
+                || frequency == Layout.HYPHENATION_FREQUENCY_NORMAL_FAST;
+    }
+
     private static ParagraphInfo[] createMeasuredParagraphsFromPrecomputedText(
             @NonNull PrecomputedText pct, @NonNull Params params, boolean computeLayout) {
         final boolean needHyphenation = params.getBreakStrategy() != Layout.BREAK_STRATEGY_SIMPLE
                 && params.getHyphenationFrequency() != Layout.HYPHENATION_FREQUENCY_NONE;
+        final int hyphenationMode;
+        if (needHyphenation) {
+            hyphenationMode = isFastHyphenation(params.getHyphenationFrequency())
+                    ? MeasuredText.Builder.HYPHENATION_MODE_FAST :
+                    MeasuredText.Builder.HYPHENATION_MODE_NORMAL;
+        } else {
+            hyphenationMode = MeasuredText.Builder.HYPHENATION_MODE_NONE;
+        }
         ArrayList<ParagraphInfo> result = new ArrayList<>();
         for (int i = 0; i < pct.getParagraphCount(); ++i) {
             final int paraStart = pct.getParagraphStart(i);
             final int paraEnd = pct.getParagraphEnd(i);
             result.add(new ParagraphInfo(paraEnd, MeasuredParagraph.buildForStaticLayout(
                     params.getTextPaint(), pct, paraStart, paraEnd, params.getTextDirection(),
-                    needHyphenation, computeLayout, pct.getMeasuredParagraph(i),
+                    hyphenationMode, computeLayout, pct.getMeasuredParagraph(i),
                     null /* no recycle */)));
         }
         return result.toArray(new ParagraphInfo[result.size()]);
@@ -421,6 +435,14 @@
         Preconditions.checkNotNull(params);
         final boolean needHyphenation = params.getBreakStrategy() != Layout.BREAK_STRATEGY_SIMPLE
                 && params.getHyphenationFrequency() != Layout.HYPHENATION_FREQUENCY_NONE;
+        final int hyphenationMode;
+        if (needHyphenation) {
+            hyphenationMode = isFastHyphenation(params.getHyphenationFrequency())
+                    ? MeasuredText.Builder.HYPHENATION_MODE_FAST :
+                    MeasuredText.Builder.HYPHENATION_MODE_NORMAL;
+        } else {
+            hyphenationMode = MeasuredText.Builder.HYPHENATION_MODE_NONE;
+        }
 
         int paraEnd = 0;
         for (int paraStart = start; paraStart < end; paraStart = paraEnd) {
@@ -435,8 +457,7 @@
 
             result.add(new ParagraphInfo(paraEnd, MeasuredParagraph.buildForStaticLayout(
                     params.getTextPaint(), text, paraStart, paraEnd, params.getTextDirection(),
-                    needHyphenation, computeLayout, null /* no hint */,
-                    null /* no recycle */)));
+                    hyphenationMode, computeLayout, null /* no hint */, null /* no recycle */)));
         }
         return result.toArray(new ParagraphInfo[result.size()]);
     }
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index f99d430..6984e4d 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -591,6 +591,20 @@
         generate(b, b.mIncludePad, b.mIncludePad);
     }
 
+    private static int getBaseHyphenationFrequency(int frequency) {
+        switch (frequency) {
+            case Layout.HYPHENATION_FREQUENCY_FULL:
+            case Layout.HYPHENATION_FREQUENCY_FULL_FAST:
+                return LineBreaker.HYPHENATION_FREQUENCY_FULL;
+            case Layout.HYPHENATION_FREQUENCY_NORMAL:
+            case Layout.HYPHENATION_FREQUENCY_NORMAL_FAST:
+                return LineBreaker.HYPHENATION_FREQUENCY_NORMAL;
+            case Layout.HYPHENATION_FREQUENCY_NONE:
+            default:
+                return LineBreaker.HYPHENATION_FREQUENCY_NONE;
+        }
+    }
+
     /* package */ void generate(Builder b, boolean includepad, boolean trackpad) {
         final CharSequence source = b.mText;
         final int bufStart = b.mStart;
@@ -641,7 +655,7 @@
 
         final LineBreaker lineBreaker = new LineBreaker.Builder()
                 .setBreakStrategy(b.mBreakStrategy)
-                .setHyphenationFrequency(b.mHyphenationFrequency)
+                .setHyphenationFrequency(getBaseHyphenationFrequency(b.mHyphenationFrequency))
                 // TODO: Support more justification mode, e.g. letter spacing, stretching.
                 .setJustificationMode(b.mJustificationMode)
                 .setIndents(indents)
diff --git a/core/java/android/util/BackupUtils.java b/core/java/android/util/BackupUtils.java
index 474ceda..4fcb13c 100644
--- a/core/java/android/util/BackupUtils.java
+++ b/core/java/android/util/BackupUtils.java
@@ -37,6 +37,10 @@
         public BadVersionException(String message) {
             super(message);
         }
+
+        public BadVersionException(String message, Throwable throwable) {
+            super(message, throwable);
+        }
     }
 
     public static String readString(DataInputStream in) throws IOException {
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index 12bcd8b..b5fe4f5 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -62,6 +62,10 @@
  * another buffer allocation and copy, and even more pressure on the gc.
  * That means that if your log message is filtered out, you might be doing
  * significant work and incurring significant overhead.
+ *
+ * <p>When calling the log methods that take a Throwable parameter,
+ * if any of the throwables in the cause chain is an <code>UnknownHostException</code>,
+ * then the stack trace is not logged.
  */
 public final class Log {
     /** @hide */
@@ -341,6 +345,9 @@
 
     /**
      * Handy function to get a loggable stack trace from a Throwable
+
+     * <p>If any of the throwables in the cause chain is an <code>UnknownHostException</code>,
+     * this returns an empty string.
      * @param tr An exception to log
      */
     @NonNull
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 9cd8313..de56d3a 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -151,8 +151,7 @@
             if (interrogatingPid == mMyProcessId && interrogatingTid == mMyLooperThreadId
                     && mHandler.hasAccessibilityCallback(message)) {
                 AccessibilityInteractionClient.getInstanceForThread(
-                        interrogatingTid, /* initializeCache= */true)
-                        .setSameThreadMessage(message);
+                        interrogatingTid).setSameThreadMessage(message);
             } else {
                 // For messages without callback of interrogating client, just handle the
                 // message immediately if this is UI thread.
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index ec613ed..c5bc99d 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -153,11 +153,20 @@
 
     /**
      * Invocation of the voice assistant via hardware button.
+     * This is a private constant.  Feel free to renumber as desired.
      * @hide
      */
     public static final int ASSISTANT_BUTTON = 10002;
 
     /**
+     * The user has performed a long press on the power button hardware that is resulting
+     * in an action being performed.
+     * This is a private constant.  Feel free to renumber as desired.
+     * @hide
+     */
+    public static final int LONG_PRESS_POWER_BUTTON = 10003;
+
+    /**
      * Flag for {@link View#performHapticFeedback(int, int)
      * View.performHapticFeedback(int, int)}: Ignore the setting in the
      * view for whether to perform haptic feedback, do it always.
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 2ee112b..12421ed 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -94,12 +94,6 @@
     void dispatchAppVisibility(boolean visible);
     void dispatchGetNewSurface();
 
-    /**
-     * Tell the window that it is either gaining or losing focus.  Keep it up
-     * to date on the current state showing navigational focus (touch mode) too.
-     */
-    void windowFocusChanged(boolean hasFocus, boolean inTouchMode);
-
     void closeSystemDialogs(String reason);
 
     /**
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 0b4857d..2c766bd 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -855,6 +855,23 @@
     void attachWindowContextToWindowToken(IBinder clientToken, IBinder token);
 
     /**
+     * Attaches a {@code clientToken} to associate with DisplayContent.
+     * <p>
+     * Note that this API should be invoked after calling
+     * {@link android.window.WindowTokenClient#attachContext(Context)}
+     * </p>
+     *
+     * @param clientToken {@link android.window.WindowContext#getWindowContextToken()
+     * the WindowContext's token}
+     * @param displayId The display associated with the window context
+     *
+     * @return the DisplayContent's {@link android.app.res.Configuration} if the Context is
+     * attached to the DisplayContent successfully. {@code null}, otherwise.
+     * @throws android.view.WindowManager.InvalidDisplayException if the display ID is invalid
+     */
+    Configuration attachToDisplayContent(IBinder clientToken, int displayId);
+
+    /**
      * Detaches {@link android.window.WindowContext} from the window manager node it's currently
      * attached to. It is no-op if the WindowContext is not attached to a window manager node.
      *
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index 02b2c5d..d609fb8 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -124,7 +124,12 @@
     public void setControl(@Nullable InsetsSourceControl control, int[] showTypes,
             int[] hideTypes) {
         super.setControl(control, showTypes, hideTypes);
-        if (control == null && !isRequestedVisibleAwaitingControl()) {
+        // TODO(b/204524304): clean-up how to deal with the timing issues of hiding IME:
+        //  1) Already requested show IME, in the meantime of WM callback the control but got null
+        //  control when relayout comes first
+        //  2) Make sure no regression on some implicit request IME visibility calls (e.g.
+        //  toggleSoftInput)
+        if (control == null && !mIsRequestedVisibleAwaitingControl) {
             hide();
             removeSurface();
         }
diff --git a/core/java/android/view/InputEventReceiver.java b/core/java/android/view/InputEventReceiver.java
index 2165f55..c9abec9 100644
--- a/core/java/android/view/InputEventReceiver.java
+++ b/core/java/android/view/InputEventReceiver.java
@@ -139,11 +139,9 @@
      * @param hasFocus if true, the window associated with this input channel has just received
      *                 focus
      *                 if false, the window associated with this input channel has just lost focus
-     * @param inTouchMode if true, the device is in touch mode
-     *                    if false, the device is not in touch mode
      */
     // Called from native code.
-    public void onFocusEvent(boolean hasFocus, boolean inTouchMode) {
+    public void onFocusEvent(boolean hasFocus) {
     }
 
     /**
@@ -175,7 +173,7 @@
      * exited touch mode.
      *
      * @param inTouchMode {@code true} if the display showing the window associated with the
-     *                                  input channel entered touch mode.
+     *                    input channel entered touch mode or {@code false} if left touch mode
      */
     public void onTouchModeChanged(boolean inTouchMode) {
     }
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 6179881..fce95c8 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -168,6 +168,16 @@
     private final DisplayCutout.ParcelableWrapper mDisplayCutout =
             new DisplayCutout.ParcelableWrapper();
 
+    /**
+     * The frame that rounded corners are relative to.
+     *
+     * There are 2 cases that will draw fake rounded corners:
+     *   1. In split-screen mode
+     *   2. Devices with a task bar
+     * We need to report these fake rounded corners to apps by re-calculating based on this frame.
+     */
+    private final Rect mRoundedCornerFrame = new Rect();
+
     /** The rounded corners on the display */
     private RoundedCorners mRoundedCorners = RoundedCorners.NO_ROUNDED_CORNERS;
 
@@ -274,12 +284,17 @@
     }
 
     private RoundedCorners calculateRelativeRoundedCorners(Rect frame) {
-        if (mDisplayFrame.equals(frame)) {
-            return mRoundedCorners;
-        }
         if (frame == null) {
             return RoundedCorners.NO_ROUNDED_CORNERS;
         }
+        // If mRoundedCornerFrame is set, we should calculate the new RoundedCorners based on this
+        // frame. It's used for split-screen mode and devices with a task bar.
+        if (!mRoundedCornerFrame.isEmpty() && !mRoundedCornerFrame.equals(mDisplayFrame)) {
+            return mRoundedCorners.insetWithFrame(frame, mRoundedCornerFrame);
+        }
+        if (mDisplayFrame.equals(frame)) {
+            return mRoundedCorners;
+        }
         final int insetLeft = frame.left - mDisplayFrame.left;
         final int insetTop = frame.top - mDisplayFrame.top;
         final int insetRight = mDisplayFrame.right - frame.right;
@@ -530,6 +545,15 @@
         return mRoundedCorners;
     }
 
+    /**
+     * Set the frame that will be used to calculate the rounded corners.
+     *
+     * @see #mRoundedCornerFrame
+     */
+    public void setRoundedCornerFrame(Rect frame) {
+        mRoundedCornerFrame.set(frame);
+    }
+
     public void setPrivacyIndicatorBounds(PrivacyIndicatorBounds bounds) {
         mPrivacyIndicatorBounds = bounds;
     }
@@ -575,6 +599,7 @@
         mDisplayFrame.scale(scale);
         mDisplayCutout.scale(scale);
         mRoundedCorners = mRoundedCorners.scale(scale);
+        mRoundedCornerFrame.scale(scale);
         mPrivacyIndicatorBounds = mPrivacyIndicatorBounds.scale(scale);
         for (int i = 0; i < SIZE; i++) {
             final InsetsSource source = mSources[i];
@@ -596,6 +621,7 @@
         mDisplayFrame.set(other.mDisplayFrame);
         mDisplayCutout.set(other.mDisplayCutout);
         mRoundedCorners = other.getRoundedCorners();
+        mRoundedCornerFrame.set(other.mRoundedCornerFrame);
         mPrivacyIndicatorBounds = other.getPrivacyIndicatorBounds();
         if (copySources) {
             for (int i = 0; i < SIZE; i++) {
@@ -620,6 +646,7 @@
         mDisplayFrame.set(other.mDisplayFrame);
         mDisplayCutout.set(other.mDisplayCutout);
         mRoundedCorners = other.getRoundedCorners();
+        mRoundedCornerFrame.set(other.mRoundedCornerFrame);
         mPrivacyIndicatorBounds = other.getPrivacyIndicatorBounds();
         final ArraySet<Integer> t = toInternalType(types);
         for (int i = t.size() - 1; i >= 0; i--) {
@@ -740,6 +767,7 @@
         pw.println(newPrefix + "mDisplayFrame=" + mDisplayFrame);
         pw.println(newPrefix + "mDisplayCutout=" + mDisplayCutout.get());
         pw.println(newPrefix + "mRoundedCorners=" + mRoundedCorners);
+        pw.println(newPrefix + "mRoundedCornerFrame=" + mRoundedCornerFrame);
         pw.println(newPrefix + "mPrivacyIndicatorBounds=" + mPrivacyIndicatorBounds);
         for (int i = 0; i < SIZE; i++) {
             InsetsSource source = mSources[i];
@@ -836,6 +864,7 @@
         if (!mDisplayFrame.equals(state.mDisplayFrame)
                 || !mDisplayCutout.equals(state.mDisplayCutout)
                 || !mRoundedCorners.equals(state.mRoundedCorners)
+                || !mRoundedCornerFrame.equals(state.mRoundedCornerFrame)
                 || !mPrivacyIndicatorBounds.equals(state.mPrivacyIndicatorBounds)) {
             return false;
         }
@@ -861,7 +890,7 @@
     @Override
     public int hashCode() {
         return Objects.hash(mDisplayFrame, mDisplayCutout, Arrays.hashCode(mSources),
-                mRoundedCorners, mPrivacyIndicatorBounds);
+                mRoundedCorners, mPrivacyIndicatorBounds, mRoundedCornerFrame);
     }
 
     public InsetsState(Parcel in) {
@@ -879,6 +908,7 @@
         mDisplayCutout.writeToParcel(dest, flags);
         dest.writeTypedArray(mSources, 0 /* parcelableFlags */);
         dest.writeTypedObject(mRoundedCorners, flags);
+        mRoundedCornerFrame.writeToParcel(dest, flags);
         dest.writeTypedObject(mPrivacyIndicatorBounds, flags);
     }
 
@@ -898,6 +928,7 @@
         mDisplayCutout.readFromParcel(in);
         in.readTypedArray(mSources, InsetsSource.CREATOR);
         mRoundedCorners = in.readTypedObject(RoundedCorners.CREATOR);
+        mRoundedCornerFrame.readFromParcel(in);
         mPrivacyIndicatorBounds = in.readTypedObject(PrivacyIndicatorBounds.CREATOR);
     }
 
@@ -914,6 +945,7 @@
                 + "mDisplayFrame=" + mDisplayFrame
                 + ", mDisplayCutout=" + mDisplayCutout
                 + ", mRoundedCorners=" + mRoundedCorners
+                + "  mRoundedCornerFrame=" + mRoundedCornerFrame
                 + ", mPrivacyIndicatorBounds=" + mPrivacyIndicatorBounds
                 + ", mSources= { " + joiner
                 + " }";
diff --git a/core/java/android/view/KeyCharacterMap.java b/core/java/android/view/KeyCharacterMap.java
index aa1acc1..a6f88a7 100644
--- a/core/java/android/view/KeyCharacterMap.java
+++ b/core/java/android/view/KeyCharacterMap.java
@@ -709,8 +709,8 @@
     }
 
     /**
-     * Queries the framework about whether any physical keys exist on the
-     * any keyboard attached to the device that are capable of producing the given key code.
+     * Queries the framework about whether any physical keys exist on any currently attached input
+     * devices that are capable of producing the given key code.
      *
      * @param keyCode The key code to query.
      * @return True if at least one attached keyboard supports the specified key code.
@@ -720,9 +720,8 @@
     }
 
     /**
-     * Queries the framework about whether any physical keys exist on the
-     * any keyboard attached to the device that are capable of producing the given
-     * array of key codes.
+     * Queries the framework about whether any physical keys exist on any currently attached input
+     * devices that are capable of producing the given array of key codes.
      *
      * @param keyCodes The array of key codes to query.
      * @return A new array of the same size as the key codes array whose elements
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 1460cb2..c3a638c 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -295,7 +295,8 @@
     /** Key code constant: Fast Forward media key. */
     public static final int KEYCODE_MEDIA_FAST_FORWARD = 90;
     /** Key code constant: Mute key.
-     * Mutes the microphone, unlike {@link #KEYCODE_VOLUME_MUTE}. */
+     * Mute key for the microphone (unlike {@link #KEYCODE_VOLUME_MUTE}, which is the speaker mute
+     * key). */
     public static final int KEYCODE_MUTE            = 91;
     /** Key code constant: Page Up key. */
     public static final int KEYCODE_PAGE_UP         = 92;
@@ -482,9 +483,10 @@
     /** Key code constant: Numeric keypad ')' key. */
     public static final int KEYCODE_NUMPAD_RIGHT_PAREN = 163;
     /** Key code constant: Volume Mute key.
-     * Mutes the speaker, unlike {@link #KEYCODE_MUTE}.
-     * This key should normally be implemented as a toggle such that the first press
-     * mutes the speaker and the second press restores the original volume. */
+     * Mute key for speaker (unlike {@link #KEYCODE_MUTE}, which is the mute key for the
+     * microphone). This key should normally be implemented as a toggle such that the first press
+     * mutes the speaker and the second press restores the original volume.
+     */
     public static final int KEYCODE_VOLUME_MUTE     = 164;
     /** Key code constant: Info key.
      * Common on TV remotes to show additional information related to what is
diff --git a/core/java/android/view/RoundedCorners.java b/core/java/android/view/RoundedCorners.java
index 6079d8e..3eade77 100644
--- a/core/java/android/view/RoundedCorners.java
+++ b/core/java/android/view/RoundedCorners.java
@@ -28,7 +28,7 @@
 import android.annotation.Nullable;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
-import android.graphics.Point;
+import android.graphics.Rect;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.DisplayUtils;
@@ -322,24 +322,71 @@
     /**
      * Insets the reference frame of the rounded corners.
      *
+     * @param frame the frame of a window or any rectangle bounds
+     * @param roundedCornerFrame the frame that used to calculate relative {@link RoundedCorner}
+     * @return a copy of this instance which has been inset
+     */
+    public RoundedCorners insetWithFrame(Rect frame, Rect roundedCornerFrame) {
+        int insetLeft = frame.left - roundedCornerFrame.left;
+        int insetTop = frame.top - roundedCornerFrame.top;
+        int insetRight = roundedCornerFrame.right - frame.right;
+        int insetBottom = roundedCornerFrame.bottom - frame.bottom;
+        final RoundedCorner[] roundedCorners = new RoundedCorner[ROUNDED_CORNER_POSITION_LENGTH];
+        int centerX, centerY;
+        for (int i = 0; i < ROUNDED_CORNER_POSITION_LENGTH; i++) {
+            if (mRoundedCorners[i].isEmpty()) {
+                roundedCorners[i] = new RoundedCorner(i);
+                continue;
+            }
+            final int radius = mRoundedCorners[i].getRadius();
+            switch (i) {
+                case POSITION_TOP_LEFT:
+                    centerX = radius;
+                    centerY = radius;
+                    break;
+                case POSITION_TOP_RIGHT:
+                    centerX = roundedCornerFrame.width() - radius;
+                    centerY = radius;
+                    break;
+                case POSITION_BOTTOM_RIGHT:
+                    centerX = roundedCornerFrame.width() - radius;
+                    centerY = roundedCornerFrame.height() - radius;
+                    break;
+                case POSITION_BOTTOM_LEFT:
+                    centerX = radius;
+                    centerY = roundedCornerFrame.height() - radius;
+                    break;
+                default:
+                    throw new IllegalArgumentException(
+                            "The position is not one of the RoundedCornerPosition =" + i);
+            }
+            roundedCorners[i] = insetRoundedCorner(i, radius, centerX, centerY, insetLeft, insetTop,
+                    insetRight, insetBottom);
+        }
+        return new RoundedCorners(roundedCorners);
+    }
+
+    /**
+     * Insets the reference frame of the rounded corners.
+     *
      * @return a copy of this instance which has been inset
      */
     public RoundedCorners inset(int insetLeft, int insetTop, int insetRight, int insetBottom) {
         final RoundedCorner[] roundedCorners = new RoundedCorner[ROUNDED_CORNER_POSITION_LENGTH];
         for (int i = 0; i < ROUNDED_CORNER_POSITION_LENGTH; i++) {
-            roundedCorners[i] = insetRoundedCorner(i, insetLeft, insetTop, insetRight, insetBottom);
+            roundedCorners[i] = insetRoundedCorner(i, mRoundedCorners[i].getRadius(),
+                    mRoundedCorners[i].getCenter().x, mRoundedCorners[i].getCenter().y, insetLeft,
+                    insetTop, insetRight, insetBottom);
         }
         return new RoundedCorners(roundedCorners);
     }
 
-    private RoundedCorner insetRoundedCorner(@Position int position, int insetLeft,
-            int insetTop, int insetRight, int insetBottom) {
+    private RoundedCorner insetRoundedCorner(@Position int position, int radius, int centerX,
+            int centerY, int insetLeft, int insetTop, int insetRight, int insetBottom) {
         if (mRoundedCorners[position].isEmpty()) {
             return new RoundedCorner(position);
         }
 
-        final int radius = mRoundedCorners[position].getRadius();
-        final Point center = mRoundedCorners[position].getCenter();
         boolean hasRoundedCorner;
         switch (position) {
             case POSITION_TOP_LEFT:
@@ -360,8 +407,8 @@
         }
         return new RoundedCorner(
                 position, radius,
-                hasRoundedCorner ? center.x - insetLeft : 0,
-                hasRoundedCorner ? center.y - insetTop : 0);
+                hasRoundedCorner ? centerX - insetLeft : 0,
+                hasRoundedCorner ? centerY - insetTop : 0);
     }
 
     /**
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 7af77ca..00754af 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -613,7 +613,10 @@
         // If there's no arguments, eg 'dumpsys gfxinfo', then dump everything.
         // If there's a targetted package, eg 'dumpsys gfxinfo com.android.systemui', then only
         // dump the summary information
-        int flags = (args == null || args.length == 0) ? FLAG_DUMP_ALL : 0;
+        if (args == null || args.length == 0) {
+            return FLAG_DUMP_ALL;
+        }
+        int flags = 0;
         for (int i = 0; i < args.length; i++) {
             switch (args[i]) {
                 case "framestats":
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ce96eca..0c30cbb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1554,9 +1554,14 @@
 
     void handleAppVisibility(boolean visible) {
         if (mAppVisible != visible) {
+            final boolean previousVisible = getHostVisibility() == View.VISIBLE;
             mAppVisible = visible;
-            mAppVisibilityChanged = true;
-            scheduleTraversals();
+            final boolean currentVisible = getHostVisibility() == View.VISIBLE;
+            // Root view only cares about whether it is visible or not.
+            if (previousVisible != currentVisible) {
+                mAppVisibilityChanged = true;
+                scheduleTraversals();
+            }
             if (!mAppVisible) {
                 WindowManagerGlobal.trimForeground();
             }
@@ -1846,8 +1851,13 @@
                 renderer.setStopped(mStopped);
             }
             if (!mStopped) {
-                mNewSurfaceNeeded = true;
-                scheduleTraversals();
+                // Unnecessary to traverse if the window is not yet visible.
+                if (getHostVisibility() == View.VISIBLE) {
+                    // Make sure that relayoutWindow will be called to get valid surface because
+                    // the previous surface may have been released.
+                    mAppVisibilityChanged = true;
+                    scheduleTraversals();
+                }
             } else {
                 if (renderer != null) {
                     renderer.destroyHardwareResources(mView);
@@ -2028,7 +2038,8 @@
     }
 
     int getHostVisibility() {
-        return (mAppVisible || mForceDecorViewVisibility) ? mView.getVisibility() : View.GONE;
+        return mView != null && (mAppVisible || mForceDecorViewVisibility)
+                ? mView.getVisibility() : View.GONE;
     }
 
     /**
@@ -8705,8 +8716,8 @@
         }
 
         @Override
-        public void onFocusEvent(boolean hasFocus, boolean inTouchMode) {
-            windowFocusChanged(hasFocus, inTouchMode);
+        public void onFocusEvent(boolean hasFocus) {
+            windowFocusChanged(hasFocus);
         }
 
         @Override
@@ -8975,9 +8986,7 @@
     /**
      * Notifies this {@link ViewRootImpl} object that window focus has changed.
      */
-    public void windowFocusChanged(boolean hasFocus, boolean unusedInTouchMode) {
-        // TODO(b/193718270): Remove inTouchMode parameter from this method and update related code
-        //     accordingly.
+    public void windowFocusChanged(boolean hasFocus) {
         synchronized (this) {
             mWindowFocusChanged = true;
             mUpcomingWindowFocus = hasFocus;
@@ -9731,14 +9740,6 @@
             }
         }
 
-        @Override
-        public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
-            final ViewRootImpl viewAncestor = mViewAncestor.get();
-            if (viewAncestor != null) {
-                viewAncestor.windowFocusChanged(hasFocus, inTouchMode);
-            }
-        }
-
         private static int checkCallingPermission(String permission) {
             try {
                 return ActivityManager.getService().checkPermission(
@@ -10426,7 +10427,7 @@
 
     @Override
     public boolean applyTransactionOnDraw(@NonNull SurfaceControl.Transaction t) {
-        if (mRemoved) {
+        if (mRemoved || !isHardwareEnabled()) {
             t.apply();
         } else {
             registerRtFrameCallback(frame -> mergeWithNextTransaction(t, frame));
diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java
index efffa2b..9793f8c 100644
--- a/core/java/android/view/ViewRootInsetsControllerHost.java
+++ b/core/java/android/view/ViewRootInsetsControllerHost.java
@@ -133,7 +133,7 @@
             //  frame instead.
             final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
             mApplier.applyParams(t, params);
-            mApplier.applyTransaction(t, -1);
+            t.apply();
         }
     }
 
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 8287de2..f69bb6a 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -129,17 +129,15 @@
 
 /**
  * The interface that apps use to talk to the window manager.
- * </p><p>
- * Each window manager instance is bound to a particular {@link Display}.
- * To obtain a {@link WindowManager} for a different display, use
- * {@link Context#createDisplayContext} to obtain a {@link Context} for that
- * display, then use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code>
- * to get the WindowManager.
- * </p><p>
- * The simplest way to show a window on another display is to create a
- * {@link Presentation}.  The presentation will automatically obtain a
- * {@link WindowManager} and {@link Context} for that display.
- * </p>
+ * <p>
+ * Each window manager instance is bound to a {@link Display}. To obtain the
+ * <code>WindowManager</code> associated with a display,
+ * call {@link Context#createWindowContext(Display, int, Bundle)} to get the display's UI context,
+ * then call {@link Context#getSystemService(String)} or {@link Context#getSystemService(Class)} on
+ * the UI context.
+ * <p>
+ * The simplest way to show a window on a particular display is to create a {@link Presentation},
+ * which automatically obtains a <code>WindowManager</code> and context for the display.
  */
 @SystemService(Context.WINDOW_SERVICE)
 public interface WindowManager extends ViewManager {
@@ -3574,6 +3572,17 @@
         public Insets providedInternalImeInsets = Insets.NONE;
 
         /**
+         * If specified, the frame that used to calculate relative {@link RoundedCorner} will be
+         * the window frame of this window minus the insets that this window provides.
+         *
+         * Task bar will draw fake rounded corners above itself, so we need this insets to calculate
+         * correct rounded corners for this window.
+         *
+         * @hide
+         */
+        public boolean insetsRoundedCornerFrame = false;
+
+        /**
          * {@link LayoutParams} to be applied to the window when layout with a assigned rotation.
          * This will make layout during rotation change smoothly.
          *
@@ -3948,6 +3957,7 @@
             }
             providedInternalInsets.writeToParcel(out, 0 /* parcelableFlags */);
             providedInternalImeInsets.writeToParcel(out, 0 /* parcelableFlags */);
+            out.writeBoolean(insetsRoundedCornerFrame);
             if (paramsForRotation != null) {
                 checkNonRecursiveParams();
                 out.writeInt(paramsForRotation.length);
@@ -4028,6 +4038,7 @@
             }
             providedInternalInsets = Insets.CREATOR.createFromParcel(in);
             providedInternalImeInsets = Insets.CREATOR.createFromParcel(in);
+            insetsRoundedCornerFrame = in.readBoolean();
             int paramsForRotationLength = in.readInt();
             if (paramsForRotationLength > 0) {
                 paramsForRotation = new LayoutParams[paramsForRotationLength];
@@ -4339,6 +4350,11 @@
                 changes |= LAYOUT_CHANGED;
             }
 
+            if (insetsRoundedCornerFrame != o.insetsRoundedCornerFrame) {
+                insetsRoundedCornerFrame = o.insetsRoundedCornerFrame;
+                changes |= LAYOUT_CHANGED;
+            }
+
             if (!Arrays.equals(paramsForRotation, o.paramsForRotation)) {
                 paramsForRotation = o.paramsForRotation;
                 checkNonRecursiveParams();
@@ -4548,6 +4564,10 @@
                 sb.append(" providedInternalImeInsets=");
                 sb.append(providedInternalImeInsets);
             }
+            if (insetsRoundedCornerFrame) {
+                sb.append(" insetsRoundedCornerFrame=");
+                sb.append(insetsRoundedCornerFrame);
+            }
             if (paramsForRotation != null && paramsForRotation.length != 0) {
                 sb.append(System.lineSeparator());
                 sb.append(prefix).append("  paramsForRotation=");
@@ -4770,6 +4790,16 @@
                     return Integer.toString(inputFeature);
             }
         }
+
+        /**
+         * True if the window should consume all pointer events itself, regardless of whether they
+         * are inside of the window. If the window is modal, its touchable region will expand to the
+         * size of its task.
+         * @hide
+         */
+        public boolean isModal() {
+            return (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
+        }
     }
 
     /**
diff --git a/core/java/android/view/WindowManagerPolicyConstants.java b/core/java/android/view/WindowManagerPolicyConstants.java
index e634d60..94f6333 100644
--- a/core/java/android/view/WindowManagerPolicyConstants.java
+++ b/core/java/android/view/WindowManagerPolicyConstants.java
@@ -236,6 +236,9 @@
      */
     int LAYER_OFFSET_THUMBNAIL = WINDOW_LAYER_MULTIPLIER - 1;
 
+    // TODO(b/207185041): Remove this divider workaround after we full remove leagacy split and
+    //                    make app pair split only have single root then we can just attach the
+    //                    divider to the single root task in shell.
     int SPLIT_DIVIDER_LAYER = TYPE_LAYER_MULTIPLIER * 3;
     int WATERMARK_LAYER = TYPE_LAYER_MULTIPLIER * 100;
     int STRICT_MODE_LAYER = TYPE_LAYER_MULTIPLIER * 101;
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index dc01990..91ef8a5 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -20,6 +20,7 @@
 import static android.view.accessibility.AccessibilityNodeInfo.FOCUS_ACCESSIBILITY;
 
 import android.os.Build;
+import android.os.SystemClock;
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.LongArray;
@@ -71,6 +72,11 @@
 
     private long mAccessibilityFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
     private long mInputFocus = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+    /**
+     * The event time of the {@link AccessibilityEvent} which presents the populated windows cache
+     * before it is stale.
+     */
+    private long mValidWindowCacheTimeStamp = 0;
 
     private int mAccessibilityFocusedWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
     private int mInputFocusWindow = AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
@@ -97,13 +103,20 @@
      * The key of SparseArray is display ID.
      *
      * @param windowsOnAllDisplays The accessibility windows of all displays.
+     * @param populationTimeStamp The timestamp from {@link SystemClock#uptimeMillis()} when the
+     *                            client requests the data.
      */
     public void setWindowsOnAllDisplays(
-            SparseArray<List<AccessibilityWindowInfo>> windowsOnAllDisplays) {
+            SparseArray<List<AccessibilityWindowInfo>> windowsOnAllDisplays,
+            long populationTimeStamp) {
         synchronized (mLock) {
             if (DEBUG) {
                 Log.i(LOG_TAG, "Set windows");
             }
+            if (mValidWindowCacheTimeStamp > populationTimeStamp) {
+                // Discard the windows because it might be stale.
+                return;
+            }
             clearWindowCacheLocked();
             if (windowsOnAllDisplays == null) {
                 return;
@@ -224,6 +237,7 @@
                 } break;
 
                 case AccessibilityEvent.TYPE_WINDOWS_CHANGED:
+                    mValidWindowCacheTimeStamp = event.getEventTime();
                     if (event.getWindowChanges()
                             == AccessibilityEvent.WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED) {
                         // Don't need to clear all cache. Unless the changes are related to
@@ -232,6 +246,7 @@
                         break;
                     }
                 case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED: {
+                    mValidWindowCacheTimeStamp = event.getEventTime();
                     clear();
                 } break;
             }
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 6975bb2..dc4c59a 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -115,13 +115,13 @@
         from a window, mapping from windowId -> timestamp. */
     private static final SparseLongArray sScrollingWindows = new SparseLongArray();
 
-    private static AccessibilityCache sAccessibilityCache;
+    private static SparseArray<AccessibilityCache> sCaches = new SparseArray<>();
 
     private final AtomicInteger mInteractionIdCounter = new AtomicInteger();
 
     private final Object mInstanceLock = new Object();
 
-    private final AccessibilityManager  mAccessibilityManager;
+    private final AccessibilityManager mAccessibilityManager;
 
     private volatile int mInteractionId = -1;
     private volatile int mCallingUid = Process.INVALID_UID;
@@ -150,7 +150,37 @@
     @UnsupportedAppUsage()
     public static AccessibilityInteractionClient getInstance() {
         final long threadId = Thread.currentThread().getId();
-        return getInstanceForThread(threadId, true);
+        return getInstanceForThread(threadId);
+    }
+
+    /**
+     * <strong>Note:</strong> We keep one instance per interrogating thread since
+     * the instance contains state which can lead to undesired thread interleavings.
+     * We do not have a thread local variable since other threads should be able to
+     * look up the correct client knowing a thread id. See ViewRootImpl for details.
+     *
+     * @return The client for a given <code>threadId</code>.
+     */
+    public static AccessibilityInteractionClient getInstanceForThread(long threadId) {
+        synchronized (sStaticLock) {
+            AccessibilityInteractionClient client = sClients.get(threadId);
+            if (client == null) {
+                client = new AccessibilityInteractionClient();
+                sClients.put(threadId, client);
+            }
+            return client;
+        }
+    }
+
+    /**
+     * @return The client for the current thread.
+     */
+    public static AccessibilityInteractionClient getInstance(Context context) {
+        final long threadId = Thread.currentThread().getId();
+        if (context != null) {
+            return getInstanceForThread(threadId, context);
+        }
+        return getInstanceForThread(threadId);
     }
 
     /**
@@ -162,61 +192,11 @@
      * @return The client for a given <code>threadId</code>.
      */
     public static AccessibilityInteractionClient getInstanceForThread(long threadId,
-            boolean initializeCache) {
-        synchronized (sStaticLock) {
-            AccessibilityInteractionClient client = sClients.get(threadId);
-            if (client == null) {
-                if (Binder.getCallingUid() == Process.SYSTEM_UID) {
-                    // Don't initialize a cache for the system process
-                    client = new AccessibilityInteractionClient(false);
-                } else {
-                    client = new AccessibilityInteractionClient(initializeCache);
-                }
-                sClients.put(threadId, client);
-            }
-            return client;
-        }
-    }
-
-    /**
-     * @return The client for the current thread.
-     */
-    public static AccessibilityInteractionClient getInstance(Context context) {
-        return getInstance(/* initializeCache= */true, context);
-    }
-
-    /**
-     * @param initializeCache whether to initialize the cache in a new client instance
-     * @return The client for the current thread.
-     */
-    public static AccessibilityInteractionClient getInstance(boolean initializeCache,
             Context context) {
-        final long threadId = Thread.currentThread().getId();
-        if (context != null) {
-            return getInstanceForThread(threadId, initializeCache, context);
-        }
-        return getInstanceForThread(threadId, initializeCache);
-    }
-
-    /**
-     * <strong>Note:</strong> We keep one instance per interrogating thread since
-     * the instance contains state which can lead to undesired thread interleavings.
-     * We do not have a thread local variable since other threads should be able to
-     * look up the correct client knowing a thread id. See ViewRootImpl for details.
-     *
-     * @param initializeCache whether to initialize the cache in a new client instance
-     * @return The client for a given <code>threadId</code>.
-     */
-    public static AccessibilityInteractionClient getInstanceForThread(
-            long threadId, boolean initializeCache, Context context) {
         synchronized (sStaticLock) {
             AccessibilityInteractionClient client = sClients.get(threadId);
             if (client == null) {
-                if (Binder.getCallingUid() == Process.SYSTEM_UID) {
-                    client = new AccessibilityInteractionClient(false, context);
-                } else {
-                    client = new AccessibilityInteractionClient(initializeCache, context);
-                }
+                client = new AccessibilityInteractionClient(context);
                 sClients.put(threadId, client);
             }
             return client;
@@ -238,12 +218,30 @@
     /**
      * Adds a cached accessibility service connection.
      *
+     * Adds a cache if {@code initializeCache} is true
      * @param connectionId The connection id.
      * @param connection The connection.
+     * @param initializeCache whether to initialize a cache
      */
-    public static void addConnection(int connectionId, IAccessibilityServiceConnection connection) {
+    public static void addConnection(int connectionId, IAccessibilityServiceConnection connection,
+            boolean initializeCache) {
         synchronized (sConnectionCache) {
             sConnectionCache.put(connectionId, connection);
+            if (!initializeCache) {
+                return;
+            }
+            sCaches.put(connectionId, new AccessibilityCache(
+                        new AccessibilityCache.AccessibilityNodeRefresher()));
+        }
+    }
+
+    /**
+     * Gets a cached associated with the connection id if available.
+     *
+     */
+    public static AccessibilityCache getCache(int connectionId) {
+        synchronized (sConnectionCache) {
+            return sCaches.get(connectionId);
         }
     }
 
@@ -255,6 +253,7 @@
     public static void removeConnection(int connectionId) {
         synchronized (sConnectionCache) {
             sConnectionCache.remove(connectionId);
+            sCaches.remove(connectionId);
         }
     }
 
@@ -263,32 +262,21 @@
      * tests need to be able to verify this class's interactions with the cache
      */
     @VisibleForTesting
-    public static void setCache(AccessibilityCache cache) {
-        sAccessibilityCache = cache;
+    public static void setCache(int connectionId, AccessibilityCache cache) {
+        synchronized (sConnectionCache) {
+            sCaches.put(connectionId, cache);
+        }
     }
 
     private AccessibilityInteractionClient() {
         /* reducing constructor visibility */
-        this(true);
-    }
-
-    private AccessibilityInteractionClient(boolean initializeCache) {
-        initializeCache(initializeCache);
         mAccessibilityManager = null;
     }
 
-    private AccessibilityInteractionClient(boolean initializeCache, Context context) {
-        initializeCache(initializeCache);
+    private AccessibilityInteractionClient(Context context) {
         mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
     }
 
-    private static void initializeCache(boolean initialize) {
-        if (initialize && sAccessibilityCache == null) {
-            sAccessibilityCache = new AccessibilityCache(
-                    new AccessibilityCache.AccessibilityNodeRefresher());
-        }
-    }
-
     /**
      * Sets the message to be processed if the interacted view hierarchy
      * and the interacting client are running in the same thread.
@@ -333,7 +321,7 @@
      *
      * @param connectionId The id of a connection for interacting with the system.
      * @param accessibilityWindowId A unique window id. Use
-     *     {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
+     *     {@link AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
      *     to query the currently active window.
      * @param bypassCache Whether to bypass the cache.
      * @return The {@link AccessibilityWindowInfo}.
@@ -344,21 +332,28 @@
             IAccessibilityServiceConnection connection = getConnection(connectionId);
             if (connection != null) {
                 AccessibilityWindowInfo window;
-                if (!bypassCache && sAccessibilityCache != null) {
-                    window = sAccessibilityCache.getWindow(accessibilityWindowId);
-                    if (window != null) {
+                AccessibilityCache cache = getCache(connectionId);
+                if (cache != null) {
+                    if (!bypassCache) {
+                        window = cache.getWindow(accessibilityWindowId);
+                        if (window != null) {
+                            if (DEBUG) {
+                                Log.i(LOG_TAG, "Window cache hit");
+                            }
+                            if (shouldTraceClient()) {
+                                logTraceClient(connection, "getWindow cache",
+                                        "connectionId=" + connectionId + ";accessibilityWindowId="
+                                                + accessibilityWindowId + ";bypassCache=false");
+                            }
+                            return window;
+                        }
                         if (DEBUG) {
-                            Log.i(LOG_TAG, "Window cache hit");
+                            Log.i(LOG_TAG, "Window cache miss");
                         }
-                        if (shouldTraceClient()) {
-                            logTraceClient(connection, "getWindow cache",
-                                    "connectionId=" + connectionId + ";accessibilityWindowId="
-                                    + accessibilityWindowId + ";bypassCache=false");
-                        }
-                        return window;
                     }
+                } else {
                     if (DEBUG) {
-                        Log.i(LOG_TAG, "Window cache miss");
+                        Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
                     }
                 }
 
@@ -374,9 +369,9 @@
                             + bypassCache);
                 }
 
-                if (window != null && sAccessibilityCache != null) {
-                    if (!bypassCache) {
-                        sAccessibilityCache.addWindow(window);
+                if (window != null) {
+                    if (!bypassCache && cache != null) {
+                        cache.addWindow(window);
                     }
                     return window;
                 }
@@ -418,8 +413,9 @@
             IAccessibilityServiceConnection connection = getConnection(connectionId);
             if (connection != null) {
                 SparseArray<List<AccessibilityWindowInfo>> windows;
-                if (sAccessibilityCache != null) {
-                    windows = sAccessibilityCache.getWindowsOnAllDisplays();
+                AccessibilityCache cache = getCache(connectionId);
+                if (cache != null) {
+                    windows = cache.getWindowsOnAllDisplays();
                     if (windows != null) {
                         if (DEBUG) {
                             Log.i(LOG_TAG, "Windows cache hit");
@@ -433,10 +429,16 @@
                     if (DEBUG) {
                         Log.i(LOG_TAG, "Windows cache miss");
                     }
+                } else {
+                    if (DEBUG) {
+                        Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
+                    }
                 }
 
+                long populationTimeStamp;
                 final long identityToken = Binder.clearCallingIdentity();
                 try {
+                    populationTimeStamp = SystemClock.uptimeMillis();
                     windows = connection.getWindows();
                 } finally {
                     Binder.restoreCallingIdentity(identityToken);
@@ -445,8 +447,8 @@
                     logTraceClient(connection, "getWindows", "connectionId=" + connectionId);
                 }
                 if (windows != null) {
-                    if (sAccessibilityCache != null) {
-                        sAccessibilityCache.setWindowsOnAllDisplays(windows);
+                    if (cache != null) {
+                        cache.setWindowsOnAllDisplays(windows, populationTimeStamp);
                     }
                     return windows;
                 }
@@ -531,28 +533,35 @@
         try {
             IAccessibilityServiceConnection connection = getConnection(connectionId);
             if (connection != null) {
-                if (!bypassCache && sAccessibilityCache != null) {
-                    AccessibilityNodeInfo cachedInfo = sAccessibilityCache.getNode(
-                            accessibilityWindowId, accessibilityNodeId);
-                    if (cachedInfo != null) {
+                if (!bypassCache) {
+                    AccessibilityCache cache = getCache(connectionId);
+                    if (cache != null) {
+                        AccessibilityNodeInfo cachedInfo = cache.getNode(
+                                accessibilityWindowId, accessibilityNodeId);
+                        if (cachedInfo != null) {
+                            if (DEBUG) {
+                                Log.i(LOG_TAG, "Node cache hit for "
+                                        + idToString(accessibilityWindowId, accessibilityNodeId));
+                            }
+                            if (shouldTraceClient()) {
+                                logTraceClient(connection,
+                                        "findAccessibilityNodeInfoByAccessibilityId cache",
+                                        "connectionId=" + connectionId + ";accessibilityWindowId="
+                                                + accessibilityWindowId + ";accessibilityNodeId="
+                                                + accessibilityNodeId + ";bypassCache="
+                                                + bypassCache + ";prefetchFlags=" + prefetchFlags
+                                                + ";arguments=" + arguments);
+                            }
+                            return cachedInfo;
+                        }
                         if (DEBUG) {
-                            Log.i(LOG_TAG, "Node cache hit for "
+                            Log.i(LOG_TAG, "Node cache miss for "
                                     + idToString(accessibilityWindowId, accessibilityNodeId));
                         }
-                        if (shouldTraceClient()) {
-                            logTraceClient(connection,
-                                    "findAccessibilityNodeInfoByAccessibilityId cache",
-                                    "connectionId=" + connectionId + ";accessibilityWindowId="
-                                    + accessibilityWindowId + ";accessibilityNodeId="
-                                    + accessibilityNodeId + ";bypassCache=" + bypassCache
-                                    + ";prefetchFlags=" + prefetchFlags + ";arguments="
-                                    + arguments);
+                    } else {
+                        if (DEBUG) {
+                            Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
                         }
-                        return cachedInfo;
-                    }
-                    if (DEBUG) {
-                        Log.i(LOG_TAG, "Node cache miss for "
-                                + idToString(accessibilityWindowId, accessibilityNodeId));
                     }
                 } else {
                     // No need to prefech nodes in bypass cache case.
@@ -756,19 +765,19 @@
     }
 
     /**
-     * Finds the {@link android.view.accessibility.AccessibilityNodeInfo} that has the
+     * Finds the {@link AccessibilityNodeInfo} that has the
      * specified focus type. The search is performed in the window whose id is specified
      * and starts from the node whose accessibility id is specified.
      *
      * @param connectionId The id of a connection for interacting with the system.
      * @param accessibilityWindowId A unique window id. Use
-     *     {@link android.view.accessibility.AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
+     *     {@link AccessibilityWindowInfo#ACTIVE_WINDOW_ID}
      *     to query the currently active window. Use
-     *     {@link android.view.accessibility.AccessibilityWindowInfo#ANY_WINDOW_ID} to query all
+     *     {@link AccessibilityWindowInfo#ANY_WINDOW_ID} to query all
      *     windows
      * @param accessibilityNodeId A unique view id or virtual descendant id from
      *     where to start the search. Use
-     *     {@link android.view.accessibility.AccessibilityNodeInfo#ROOT_NODE_ID}
+     *     {@link AccessibilityNodeInfo#ROOT_NODE_ID}
      *     to start from the root.
      * @param focusType The focus type.
      * @return The accessibility focused {@link AccessibilityNodeInfo}.
@@ -779,8 +788,9 @@
         try {
             IAccessibilityServiceConnection connection = getConnection(connectionId);
             if (connection != null) {
-                if (sAccessibilityCache != null) {
-                    AccessibilityNodeInfo cachedInfo = sAccessibilityCache.getFocus(focusType,
+                AccessibilityCache cache = getCache(connectionId);
+                if (cache != null) {
+                    AccessibilityNodeInfo cachedInfo = cache.getFocus(focusType,
                             accessibilityNodeId, accessibilityWindowId);
                     if (cachedInfo != null) {
                         if (DEBUG) {
@@ -794,6 +804,10 @@
                         Log.i(LOG_TAG, "Focused node cache miss with "
                                 + idToString(accessibilityWindowId, accessibilityNodeId));
                     }
+                } else {
+                    if (DEBUG) {
+                        Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
+                    }
                 }
                 final int interactionId = mInteractionIdCounter.getAndIncrement();
                 if (shouldTraceClient()) {
@@ -954,16 +968,25 @@
     }
 
     /**
-     * Clears the accessibility cache.
+     * Clears the cache associated with {@code connectionId}
+     * @param connectionId the connection id
+     * TODO(207417185): Modify UnsupportedAppUsage
      */
     @UnsupportedAppUsage()
-    public void clearCache() {
-        if (sAccessibilityCache != null) {
-            sAccessibilityCache.clear();
+    public void clearCache(int connectionId) {
+        AccessibilityCache cache = getCache(connectionId);
+        if (cache == null) {
+            return;
         }
+        cache.clear();
     }
 
-    public void onAccessibilityEvent(AccessibilityEvent event) {
+    /**
+     * Informs the cache associated with {@code connectionId} of {@code event}
+     * @param event the event
+     * @param connectionId the connection id
+     */
+    public void onAccessibilityEvent(AccessibilityEvent event, int connectionId) {
         switch (event.getEventType()) {
             case AccessibilityEvent.TYPE_VIEW_SCROLLED:
                 updateScrollingWindow(event.getWindowId(), SystemClock.uptimeMillis());
@@ -976,9 +999,14 @@
             default:
                 break;
         }
-        if (sAccessibilityCache != null) {
-            sAccessibilityCache.onAccessibilityEvent(event);
+        AccessibilityCache cache = getCache(connectionId);
+        if (cache == null) {
+            if (DEBUG) {
+                Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
+            }
+            return;
         }
+        cache.onAccessibilityEvent(event);
     }
 
     /**
@@ -1214,8 +1242,15 @@
                 }
             }
             info.setSealed(true);
-            if (!bypassCache && sAccessibilityCache != null) {
-                sAccessibilityCache.add(info);
+            if (!bypassCache) {
+                AccessibilityCache cache = getCache(connectionId);
+                if (cache == null) {
+                    if (DEBUG) {
+                        Log.w(LOG_TAG, "Cache is null for connection id: " + connectionId);
+                    }
+                    return;
+                }
+                cache.add(info);
             }
         }
     }
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index bb3f4e5..dc61727 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -121,6 +121,8 @@
     public static final int STATE_FLAG_TRACE_A11Y_INTERACTION_CLIENT_ENABLED = 0x00000400;
     /** @hide */
     public static final int STATE_FLAG_TRACE_A11Y_SERVICE_ENABLED = 0x00000800;
+    /** @hide */
+    public static final int STATE_FLAG_AUDIO_DESCRIPTION_BY_DEFAULT_ENABLED = 0x00001000;
 
     /** @hide */
     public static final int DALTONIZER_DISABLED = -1;
@@ -244,6 +246,8 @@
     @UnsupportedAppUsage(trackingBug = 123768939L)
     boolean mIsHighTextContrastEnabled;
 
+    boolean mIsAudioDescriptionByDefaultRequested;
+
     // accessibility tracing state
     int mAccessibilityTracingState = 0;
 
@@ -1293,15 +1297,19 @@
                 (stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0;
         final boolean highTextContrastEnabled =
                 (stateFlags & STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED) != 0;
+        final boolean audioDescriptionEnabled =
+                (stateFlags & STATE_FLAG_AUDIO_DESCRIPTION_BY_DEFAULT_ENABLED) != 0;
 
         final boolean wasEnabled = isEnabled();
         final boolean wasTouchExplorationEnabled = mIsTouchExplorationEnabled;
         final boolean wasHighTextContrastEnabled = mIsHighTextContrastEnabled;
 
+
         // Ensure listeners get current state from isZzzEnabled() calls.
         mIsEnabled = enabled;
         mIsTouchExplorationEnabled = touchExplorationEnabled;
         mIsHighTextContrastEnabled = highTextContrastEnabled;
+        mIsAudioDescriptionByDefaultRequested = audioDescriptionEnabled;
 
         if (wasEnabled != isEnabled()) {
             notifyAccessibilityStateChanged();
@@ -1678,6 +1686,29 @@
         }
     }
 
+    /**
+     * Determines if users want to select sound track with audio description by default.
+     *
+     * Audio description, also referred to as a video description, described video, or
+     * more precisely called a visual description, is a form of narration used to provide
+     * information surrounding key visual elements in a media work for the benefit of
+     * blind and visually impaired consumers.
+     *
+     * The method provides the preference value to content provider apps to select the
+     * default sound track during playing a video or movie.
+     *
+     * @return {@code true} if the audio description is enabled, {@code false} otherwise.
+     */
+    public boolean isAudioDescriptionRequested() {
+        synchronized (mLock) {
+            IAccessibilityManager service = getServiceLocked();
+            if (service == null) {
+                return false;
+            }
+            return mIsAudioDescriptionByDefaultRequested;
+        }
+    }
+
     private IAccessibilityManager getServiceLocked() {
         if (mService == null) {
             tryConnectToServiceLocked(null);
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 4730eaa..7680aa6 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -3957,8 +3957,10 @@
         }
 
         if (isBitSet(nonDefaultFields, fieldIndex++)) {
+            parcel.writeString(mCollectionItemInfo.getRowTitle());
             parcel.writeInt(mCollectionItemInfo.getRowIndex());
             parcel.writeInt(mCollectionItemInfo.getRowSpan());
+            parcel.writeString(mCollectionItemInfo.getColumnTitle());
             parcel.writeInt(mCollectionItemInfo.getColumnIndex());
             parcel.writeInt(mCollectionItemInfo.getColumnSpan());
             parcel.writeInt(mCollectionItemInfo.isHeading() ? 1 : 0);
@@ -4100,8 +4102,9 @@
                                      ci.mHierarchical, ci.mSelectionMode);
         CollectionItemInfo cii = other.mCollectionItemInfo;
         mCollectionItemInfo = (cii == null)  ? null
-                : new CollectionItemInfo(cii.mRowIndex, cii.mRowSpan, cii.mColumnIndex,
-                                         cii.mColumnSpan, cii.mHeading, cii.mSelected);
+                : new CollectionItemInfo(cii.mRowTitle, cii.mRowIndex, cii.mRowSpan,
+                        cii.mColumnTitle, cii.mColumnIndex, cii.mColumnSpan,
+                        cii.mHeading, cii.mSelected);
         ExtraRenderingInfo ti = other.mExtraRenderingInfo;
         mExtraRenderingInfo = (ti == null) ? null
                 : new ExtraRenderingInfo(ti);
@@ -4221,8 +4224,10 @@
         if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
         mCollectionItemInfo = isBitSet(nonDefaultFields, fieldIndex++)
                 ? CollectionItemInfo.obtain(
+                        parcel.readString(),
                         parcel.readInt(),
                         parcel.readInt(),
+                        parcel.readString(),
                         parcel.readInt(),
                         parcel.readInt(),
                         parcel.readInt() == 1,
@@ -5570,8 +5575,9 @@
          * @hide
          */
         public static CollectionItemInfo obtain(CollectionItemInfo other) {
-            return CollectionItemInfo.obtain(other.mRowIndex, other.mRowSpan, other.mColumnIndex,
-                    other.mColumnSpan, other.mHeading, other.mSelected);
+            return CollectionItemInfo.obtain(other.mRowTitle, other.mRowIndex, other.mRowSpan,
+                    other.mColumnTitle, other.mColumnIndex, other.mColumnSpan, other.mHeading,
+                    other.mSelected);
         }
 
         /**
@@ -5612,10 +5618,36 @@
          */
         public static CollectionItemInfo obtain(int rowIndex, int rowSpan,
                 int columnIndex, int columnSpan, boolean heading, boolean selected) {
+            return obtain(null, rowIndex, rowSpan, null, columnIndex,
+                    columnSpan, heading, selected);
+        }
+
+        /**
+         * Obtains a pooled instance.
+         *
+         * <p>In most situations object pooling is not beneficial. Creates a new instance using the
+         * constructor {@link
+         * AccessibilityNodeInfo.CollectionItemInfo#CollectionItemInfo(int,
+         * int, int, int, boolean, boolean)} instead.
+         *
+         * @param rowTitle The row title at which the item is located.
+         * @param rowIndex The row index at which the item is located.
+         * @param rowSpan The number of rows the item spans.
+         * @param columnTitle The column title at which the item is located.
+         * @param columnIndex The column index at which the item is located.
+         * @param columnSpan The number of columns the item spans.
+         * @param heading Whether the item is a heading. (Prefer
+         *                {@link AccessibilityNodeInfo#setHeading(boolean)})
+         * @param selected Whether the item is selected.
+         */
+        @NonNull
+        public static CollectionItemInfo obtain(@Nullable String rowTitle, int rowIndex,
+                int rowSpan, @Nullable String columnTitle, int columnIndex, int columnSpan,
+                boolean heading, boolean selected) {
             final CollectionItemInfo info = sPool.acquire();
             if (info == null) {
-                return new CollectionItemInfo(
-                        rowIndex, rowSpan, columnIndex, columnSpan, heading, selected);
+                return new CollectionItemInfo(rowTitle, rowIndex, rowSpan, columnTitle,
+                        columnIndex, columnSpan, heading, selected);
             }
 
             info.mRowIndex = rowIndex;
@@ -5624,6 +5656,8 @@
             info.mColumnSpan = columnSpan;
             info.mHeading = heading;
             info.mSelected = selected;
+            info.mRowTitle = rowTitle;
+            info.mColumnTitle = columnTitle;
             return info;
         }
 
@@ -5633,6 +5667,8 @@
         private int mColumnSpan;
         private int mRowSpan;
         private boolean mSelected;
+        private String mRowTitle;
+        private String mColumnTitle;
 
         /**
          * Creates a new instance.
@@ -5660,12 +5696,33 @@
          */
         public CollectionItemInfo(int rowIndex, int rowSpan, int columnIndex, int columnSpan,
                 boolean heading, boolean selected) {
+            this(null, rowIndex, rowSpan, null, columnIndex, columnSpan,
+                    heading, selected);
+        }
+
+        /**
+         * Creates a new instance.
+         *
+         * @param rowTitle The row title at which the item is located.
+         * @param rowIndex The row index at which the item is located.
+         * @param rowSpan The number of rows the item spans.
+         * @param columnTitle The column title at which the item is located.
+         * @param columnIndex The column index at which the item is located.
+         * @param columnSpan The number of columns the item spans.
+         * @param heading Whether the item is a heading.
+         * @param selected Whether the item is selected.
+         */
+        public CollectionItemInfo(@Nullable String rowTitle, int rowIndex, int rowSpan,
+                @Nullable String columnTitle, int columnIndex, int columnSpan, boolean heading,
+                boolean selected) {
             mRowIndex = rowIndex;
             mRowSpan = rowSpan;
             mColumnIndex = columnIndex;
             mColumnSpan = columnSpan;
             mHeading = heading;
             mSelected = selected;
+            mRowTitle = rowTitle;
+            mColumnTitle = columnTitle;
         }
 
         /**
@@ -5725,6 +5782,26 @@
         }
 
         /**
+         * Gets the row title at which the item is located.
+         *
+         * @return The row title.
+         */
+        @Nullable
+        public String getRowTitle() {
+            return mRowTitle;
+        }
+
+        /**
+         * Gets the column title at which the item is located.
+         *
+         * @return The column title.
+         */
+        @Nullable
+        public String getColumnTitle() {
+            return mColumnTitle;
+        }
+
+        /**
          * Recycles this instance.
          *
          * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
@@ -5741,6 +5818,8 @@
             mRowSpan = 0;
             mHeading = false;
             mSelected = false;
+            mRowTitle = null;
+            mColumnTitle = null;
         }
     }
 
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index 078ab25..4e8d2da 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -98,4 +98,6 @@
     int getFocusStrokeWidth();
 
     int getFocusColor();
+
+    boolean isAudioDescriptionByDefaultEnabled();
 }
diff --git a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl
index ddf68fc..67d9667 100644
--- a/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl
+++ b/core/java/android/view/accessibility/IWindowMagnificationConnection.aidl
@@ -38,9 +38,14 @@
      *                or {@link Float#NaN} to leave unchanged.
      * @param centerY the screen-relative Y coordinate around which to center,
      *                or {@link Float#NaN} to leave unchanged.
+     * @param magnificationFrameOffsetRatioX Indicate the X coordinate offset between
+     *                                       frame position X and centerX
+     * @param magnificationFrameOffsetRatioY Indicate the Y coordinate offset between
+     *                                       frame position Y and centerY
      * @param callback The callback called when the animation is completed or interrupted.
      */
     void enableWindowMagnification(int displayId, float scale, float centerX, float centerY,
+        float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
         in IRemoteMagnificationAnimationCallback callback);
 
     /**
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index f724285..3d4d9ec 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -338,7 +338,10 @@
      * Maps bitmaps to unique indicies to avoid Bitmap duplication.
      */
     @UnsupportedAppUsage
-    private BitmapCache mBitmapCache;
+    private BitmapCache mBitmapCache = new BitmapCache();
+
+    /** Cache of ApplicationInfos used by collection items. */
+    private ApplicationInfoCache mApplicationInfoCache = new ApplicationInfoCache();
 
     /**
      * Indicates whether or not this RemoteViews object is contained as a child of any other
@@ -576,7 +579,7 @@
             return 0;
         }
 
-        public void setBitmapCache(BitmapCache bitmapCache) {
+        public void setHierarchyRootData(HierarchyRootData root) {
             // Do nothing
         }
 
@@ -605,14 +608,6 @@
             return false;
         }
 
-        /**
-         * Overridden by subclasses which have (or inherit) an ApplicationInfo instance
-         * as member variable
-         */
-        public boolean hasSameAppInfo(ApplicationInfo parentInfo) {
-            return true;
-        }
-
         public void visitUris(@NonNull Consumer<Uri> visitor) {
             // Nothing to visit by default
         }
@@ -690,9 +685,8 @@
             }
         }
 
-        // Because pruning can remove the need for bitmaps, we reconstruct the bitmap cache
-        mBitmapCache = new BitmapCache();
-        setBitmapCache(mBitmapCache);
+        // Because pruning can remove the need for bitmaps, we reconstruct the caches.
+        reconstructCaches();
     }
 
     /**
@@ -938,23 +932,70 @@
         ArrayList<RemoteViews> list;
     }
 
-    private static class SetRemoteCollectionItemListAdapterAction extends Action {
+    /**
+     * Cache of {@link ApplicationInfo}s that can be used to ensure that the same
+     * {@link ApplicationInfo} instance is used throughout the RemoteViews.
+     */
+    private static class ApplicationInfoCache {
+        private final Map<Pair<String, Integer>, ApplicationInfo> mPackageUserToApplicationInfo;
+
+        ApplicationInfoCache() {
+            mPackageUserToApplicationInfo = new ArrayMap<>();
+        }
+
+        /**
+         * Adds the {@link ApplicationInfo} to the cache if it's not present. Returns either the
+         * provided {@code applicationInfo} or a previously added value with the same package name
+         * and uid.
+         */
+        @Nullable
+        ApplicationInfo getOrPut(@Nullable ApplicationInfo applicationInfo) {
+            Pair<String, Integer> key = getPackageUserKey(applicationInfo);
+            if (key == null) return null;
+            return mPackageUserToApplicationInfo.computeIfAbsent(key, ignored -> applicationInfo);
+        }
+
+        /** Puts the {@link ApplicationInfo} in the cache, replacing any previously stored value. */
+        void put(@Nullable ApplicationInfo applicationInfo) {
+            Pair<String, Integer> key = getPackageUserKey(applicationInfo);
+            if (key == null) return;
+            mPackageUserToApplicationInfo.put(key, applicationInfo);
+        }
+
+        /**
+         * Returns the currently stored {@link ApplicationInfo} from the cache matching
+         * {@code  applicationInfo}, or null if there wasn't any.
+         */
+        @Nullable ApplicationInfo get(@Nullable ApplicationInfo applicationInfo) {
+            Pair<String, Integer> key = getPackageUserKey(applicationInfo);
+            if (key == null) return null;
+            return mPackageUserToApplicationInfo.get(key);
+        }
+    }
+
+    private class SetRemoteCollectionItemListAdapterAction extends Action {
         private final RemoteCollectionItems mItems;
 
         SetRemoteCollectionItemListAdapterAction(@IdRes int id, RemoteCollectionItems items) {
             viewId = id;
             mItems = items;
+            mItems.setHierarchyRootData(getHierarchyRootData());
         }
 
         SetRemoteCollectionItemListAdapterAction(Parcel parcel) {
             viewId = parcel.readInt();
-            mItems = parcel.readTypedObject(RemoteCollectionItems.CREATOR);
+            mItems = new RemoteCollectionItems(parcel, getHierarchyRootData());
+        }
+
+        @Override
+        public void setHierarchyRootData(HierarchyRootData rootData) {
+            mItems.setHierarchyRootData(rootData);
         }
 
         @Override
         public void writeToParcel(Parcel dest, int flags) {
             dest.writeInt(viewId);
-            dest.writeTypedObject(mItems, flags);
+            mItems.writeToParcel(dest, flags, /* attached= */ true);
         }
 
         @Override
@@ -1602,8 +1643,8 @@
         }
 
         @Override
-        public void setBitmapCache(BitmapCache bitmapCache) {
-            bitmapId = bitmapCache.getBitmapId(bitmap);
+        public void setHierarchyRootData(HierarchyRootData rootData) {
+            bitmapId = rootData.mBitmapCache.getBitmapId(bitmap);
         }
 
         @Override
@@ -2220,15 +2261,6 @@
         }
     }
 
-    private void configureRemoteViewsAsChild(RemoteViews rv) {
-        rv.setBitmapCache(mBitmapCache);
-        rv.setNotRoot();
-    }
-
-    void setNotRoot() {
-        mIsRoot = false;
-    }
-
     private static boolean hasStableId(View view) {
         Object tag = view.getTag(com.android.internal.R.id.remote_views_stable_id);
         return tag != null;
@@ -2302,17 +2334,14 @@
             mNestedViews = nestedViews;
             mIndex = index;
             mStableId = stableId;
-            if (nestedViews != null) {
-                configureRemoteViewsAsChild(nestedViews);
-            }
+            nestedViews.configureAsChild(getHierarchyRootData());
         }
 
-        ViewGroupActionAdd(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info,
-                int depth, Map<Class, Object> classCookies) {
+        ViewGroupActionAdd(Parcel parcel, ApplicationInfo info, int depth) {
             viewId = parcel.readInt();
             mIndex = parcel.readInt();
             mStableId = parcel.readInt();
-            mNestedViews = new RemoteViews(parcel, bitmapCache, info, depth, classCookies);
+            mNestedViews = new RemoteViews(parcel, getHierarchyRootData(), info, depth);
             mNestedViews.addFlags(mApplyFlags);
         }
 
@@ -2324,8 +2353,8 @@
         }
 
         @Override
-        public boolean hasSameAppInfo(ApplicationInfo parentInfo) {
-            return mNestedViews.hasSameAppInfo(parentInfo);
+        public void setHierarchyRootData(HierarchyRootData root) {
+            mNestedViews.configureAsChild(root);
         }
 
         private int findViewIndexToRecycle(ViewGroup target, RemoteViews newContent) {
@@ -2494,11 +2523,6 @@
         }
 
         @Override
-        public void setBitmapCache(BitmapCache bitmapCache) {
-            mNestedViews.setBitmapCache(bitmapCache);
-        }
-
-        @Override
         public int mergeBehavior() {
             return MERGE_APPEND;
         }
@@ -3505,8 +3529,7 @@
     protected RemoteViews(ApplicationInfo application, @LayoutRes int layoutId) {
         mApplication = application;
         mLayoutId = layoutId;
-        mBitmapCache = new BitmapCache();
-        mClassCookies = null;
+        mApplicationInfoCache.put(application);
     }
 
     private boolean hasMultipleLayouts() {
@@ -3562,12 +3585,10 @@
         mLandscape = landscape;
         mPortrait = portrait;
 
-        mBitmapCache = new BitmapCache();
-        configureRemoteViewsAsChild(landscape);
-        configureRemoteViewsAsChild(portrait);
-
         mClassCookies = (portrait.mClassCookies != null)
                 ? portrait.mClassCookies : landscape.mClassCookies;
+
+        configureDescendantsAsChildren();
     }
 
     /**
@@ -3593,10 +3614,12 @@
             throw new IllegalArgumentException("Too many RemoteViews in constructor");
         }
         if (remoteViews.size() == 1) {
-            initializeFrom(remoteViews.values().iterator().next());
+            // If the map only contains a single mapping, treat this as if that RemoteViews was
+            // passed as the top-level RemoteViews.
+            RemoteViews single = remoteViews.values().iterator().next();
+            initializeFrom(single, /* hierarchyRoot= */ single);
             return;
         }
-        mBitmapCache = new BitmapCache();
         mClassCookies = initializeSizedRemoteViews(
                 remoteViews.entrySet().stream().map(
                         entry -> {
@@ -3611,6 +3634,8 @@
         mLayoutId = smallestView.mLayoutId;
         mViewId = smallestView.mViewId;
         mLightBackgroundLayoutId = smallestView.mLightBackgroundLayoutId;
+
+        configureDescendantsAsChildren();
     }
 
     // Initialize mSizedRemoteViews and return the class cookies.
@@ -3639,7 +3664,6 @@
             } else {
                 sizedRemoteViews.add(view);
             }
-            configureRemoteViewsAsChild(view);
             view.setIdealSize(size);
             if (classCookies == null) {
                 classCookies = view.mClassCookies;
@@ -3654,13 +3678,38 @@
      * Creates a copy of another RemoteViews.
      */
     public RemoteViews(RemoteViews src) {
-        initializeFrom(src);
+        initializeFrom(src, /* hierarchyRoot= */ null);
     }
 
-    private void initializeFrom(RemoteViews src) {
-        mBitmapCache = src.mBitmapCache;
+    /**
+     * No-arg constructor for use with {@link #initializeFrom(RemoteViews, RemoteViews)}. A
+     * constructor taking two RemoteViews parameters would clash with the landscape/portrait
+     * constructor.
+     */
+    private RemoteViews() {}
+
+    private static RemoteViews createInitializedFrom(@NonNull RemoteViews src,
+            @Nullable RemoteViews hierarchyRoot) {
+        RemoteViews child = new RemoteViews();
+        child.initializeFrom(src, hierarchyRoot);
+        return child;
+    }
+
+    private void initializeFrom(@NonNull RemoteViews src, @Nullable RemoteViews hierarchyRoot) {
+        if (hierarchyRoot == null || src.mIsRoot) {
+            // If there's no provided root, or if src was itself a root, then this RemoteViews is
+            // the root of the new hierarchy.
+            mIsRoot = true;
+            mBitmapCache = new BitmapCache();
+            mApplicationInfoCache = new ApplicationInfoCache();
+            hierarchyRoot = this;
+        } else {
+            // Otherwise, we're a descendant in the hierarchy.
+            mIsRoot = false;
+            mBitmapCache = hierarchyRoot.mBitmapCache;
+            mApplicationInfoCache = hierarchyRoot.mApplicationInfoCache;
+        }
         mApplication = src.mApplication;
-        mIsRoot = src.mIsRoot;
         mLayoutId = src.mLayoutId;
         mLightBackgroundLayoutId = src.mLightBackgroundLayoutId;
         mApplyFlags = src.mApplyFlags;
@@ -3669,21 +3718,21 @@
         mProviderInstanceId = src.mProviderInstanceId;
 
         if (src.hasLandscapeAndPortraitLayouts()) {
-            mLandscape = new RemoteViews(src.mLandscape);
-            mPortrait = new RemoteViews(src.mPortrait);
+            mLandscape = createInitializedFrom(src.mLandscape, hierarchyRoot);
+            mPortrait = createInitializedFrom(src.mPortrait, hierarchyRoot);
         }
 
         if (src.hasSizedRemoteViews()) {
             mSizedRemoteViews = new ArrayList<>(src.mSizedRemoteViews.size());
             for (RemoteViews srcView : src.mSizedRemoteViews) {
-                mSizedRemoteViews.add(new RemoteViews(srcView));
+                mSizedRemoteViews.add(createInitializedFrom(srcView, hierarchyRoot));
             }
         }
 
         if (src.mActions != null) {
             Parcel p = Parcel.obtain();
             p.putClassCookies(mClassCookies);
-            src.writeActionsToParcel(p);
+            src.writeActionsToParcel(p, /* flags= */ 0);
             p.setDataPosition(0);
             // Since src is already in memory, we do not care about stack overflow as it has
             // already been read once.
@@ -3691,9 +3740,11 @@
             p.recycle();
         }
 
-        // Now that everything is initialized and duplicated, setting a new BitmapCache will
-        // re-initialize the cache.
-        setBitmapCache(new BitmapCache());
+        // Now that everything is initialized and duplicated, create new caches for this
+        // RemoteViews and recursively set up all descendants.
+        if (mIsRoot) {
+            reconstructCaches();
+        }
     }
 
     /**
@@ -3702,11 +3753,11 @@
      * @param parcel
      */
     public RemoteViews(Parcel parcel) {
-        this(parcel, null, null, 0, null);
+        this(parcel, /* rootParent= */ null, /* info= */ null, /* depth= */ 0);
     }
 
-    private RemoteViews(Parcel parcel, BitmapCache bitmapCache, ApplicationInfo info, int depth,
-            Map<Class, Object> classCookies) {
+    private RemoteViews(@NonNull Parcel parcel, @Nullable HierarchyRootData rootData,
+            @Nullable ApplicationInfo info, int depth) {
         if (depth > MAX_NESTED_VIEWS
                 && (UserHandle.getAppId(Binder.getCallingUid()) != Process.SYSTEM_UID)) {
             throw new IllegalArgumentException("Too many nested views.");
@@ -3715,20 +3766,17 @@
 
         int mode = parcel.readInt();
 
-        // We only store a bitmap cache in the root of the RemoteViews.
-        if (bitmapCache == null) {
+        if (rootData == null) {
+            // We only store a bitmap cache in the root of the RemoteViews.
             mBitmapCache = new BitmapCache(parcel);
             // Store the class cookies such that they are available when we clone this RemoteView.
             mClassCookies = parcel.copyClassCookies();
         } else {
-            setBitmapCache(bitmapCache);
-            mClassCookies = classCookies;
-            setNotRoot();
+            configureAsChild(rootData);
         }
 
         if (mode == MODE_NORMAL) {
-            mApplication = parcel.readInt() == 0 ? info :
-                    ApplicationInfo.CREATOR.createFromParcel(parcel);
+            mApplication = ApplicationInfo.CREATOR.createFromParcel(parcel);
             mIdealSize = parcel.readInt() == 0 ? null : SizeF.CREATOR.createFromParcel(parcel);
             mLayoutId = parcel.readInt();
             mViewId = parcel.readInt();
@@ -3743,8 +3791,7 @@
             }
             List<RemoteViews> remoteViews = new ArrayList<>(numViews);
             for (int i = 0; i < numViews; i++) {
-                RemoteViews view = new RemoteViews(parcel, mBitmapCache, info, depth,
-                        mClassCookies);
+                RemoteViews view = new RemoteViews(parcel, getHierarchyRootData(), info, depth);
                 info = view.mApplication;
                 remoteViews.add(view);
             }
@@ -3756,9 +3803,9 @@
             mLightBackgroundLayoutId = smallestView.mLightBackgroundLayoutId;
         } else {
             // MODE_HAS_LANDSCAPE_AND_PORTRAIT
-            mLandscape = new RemoteViews(parcel, mBitmapCache, info, depth, mClassCookies);
-            mPortrait = new RemoteViews(parcel, mBitmapCache, mLandscape.mApplication, depth,
-                    mClassCookies);
+            mLandscape = new RemoteViews(parcel, getHierarchyRootData(), info, depth);
+            mPortrait =
+                    new RemoteViews(parcel, getHierarchyRootData(), mLandscape.mApplication, depth);
             mApplication = mPortrait.mApplication;
             mLayoutId = mPortrait.mLayoutId;
             mViewId = mPortrait.mViewId;
@@ -3766,6 +3813,11 @@
         }
         mApplyFlags = parcel.readInt();
         mProviderInstanceId = parcel.readLong();
+
+        // Ensure that all descendants have their caches set up recursively.
+        if (mIsRoot) {
+            configureDescendantsAsChildren();
+        }
     }
 
     private void readActionsFromParcel(Parcel parcel, int depth) {
@@ -3788,8 +3840,7 @@
             case REFLECTION_ACTION_TAG:
                 return new ReflectionAction(parcel);
             case VIEW_GROUP_ACTION_ADD_TAG:
-                return new ViewGroupActionAdd(parcel, mBitmapCache, mApplication, depth,
-                        mClassCookies);
+                return new ViewGroupActionAdd(parcel, mApplication, depth);
             case VIEW_GROUP_ACTION_REMOVE_TAG:
                 return new ViewGroupActionRemove(parcel);
             case VIEW_CONTENT_NAVIGATION_TAG:
@@ -3879,28 +3930,56 @@
     }
 
     /**
-     * Recursively sets BitmapCache in the hierarchy and update the bitmap ids.
+     * Sets the root of the hierarchy and then recursively traverses the tree to update the root
+     * and populate caches for all descendants.
      */
-    private void setBitmapCache(BitmapCache bitmapCache) {
-        mBitmapCache = bitmapCache;
+    private void configureAsChild(@NonNull HierarchyRootData rootData) {
+        mIsRoot = false;
+        mBitmapCache = rootData.mBitmapCache;
+        mApplicationInfoCache = rootData.mApplicationInfoCache;
+        mClassCookies = rootData.mClassCookies;
+        configureDescendantsAsChildren();
+    }
+
+    /**
+     * Recursively traverses the tree to update the root and populate caches for all descendants.
+     */
+    private void configureDescendantsAsChildren() {
+        // Before propagating down the tree, replace our application from the root application info
+        // cache, to ensure the same instance is present throughout the hierarchy to allow for
+        // squashing.
+        mApplication = mApplicationInfoCache.getOrPut(mApplication);
+
+        HierarchyRootData rootData = getHierarchyRootData();
         if (hasSizedRemoteViews()) {
             for (RemoteViews remoteView : mSizedRemoteViews) {
-                remoteView.setBitmapCache(bitmapCache);
+                remoteView.configureAsChild(rootData);
             }
         } else if (hasLandscapeAndPortraitLayouts()) {
-            mLandscape.setBitmapCache(bitmapCache);
-            mPortrait.setBitmapCache(bitmapCache);
+            mLandscape.configureAsChild(rootData);
+            mPortrait.configureAsChild(rootData);
         } else {
             if (mActions != null) {
-                final int count = mActions.size();
-                for (int i = 0; i < count; ++i) {
-                    mActions.get(i).setBitmapCache(bitmapCache);
+                for (Action action : mActions) {
+                    action.setHierarchyRootData(rootData);
                 }
             }
         }
     }
 
     /**
+     * Recreates caches at the root level of the hierarchy, then recursively populates the caches
+     * down the hierarchy.
+     */
+    private void reconstructCaches() {
+        if (!mIsRoot) return;
+        mBitmapCache = new BitmapCache();
+        mApplicationInfoCache = new ApplicationInfoCache();
+        mApplication = mApplicationInfoCache.getOrPut(mApplication);
+        configureDescendantsAsChildren();
+    }
+
+    /**
      * Returns an estimate of the bitmap heap memory usage for this RemoteViews.
      */
     /** @hide */
@@ -5848,21 +5927,18 @@
 
     /** @hide */
     public void updateAppInfo(@NonNull ApplicationInfo info) {
-        if (mApplication != null && mApplication.sourceDir.equals(info.sourceDir)) {
+        ApplicationInfo existing = mApplicationInfoCache.get(info);
+        if (existing != null && !existing.sourceDir.equals(info.sourceDir)) {
             // Overlay paths are generated against a particular version of an application.
             // The overlays paths of a newly upgraded application are incompatible with the
             // old version of the application.
-            mApplication = info;
+            return;
         }
-        if (hasSizedRemoteViews()) {
-            for (RemoteViews layout : mSizedRemoteViews) {
-                layout.updateAppInfo(info);
-            }
-        }
-        if (hasLandscapeAndPortraitLayouts()) {
-            mLandscape.updateAppInfo(info);
-            mPortrait.updateAppInfo(info);
-        }
+
+        // If we can update to the new AppInfo, put it in the cache and propagate the change
+        // throughout the hierarchy.
+        mApplicationInfoCache.put(info);
+        configureDescendantsAsChildren();
     }
 
     private Context getContextForResourcesEnsuringCorrectCachedApkPaths(Context context) {
@@ -6028,6 +6104,8 @@
     }
 
     public void writeToParcel(Parcel dest, int flags) {
+        boolean prevSquashingAllowed = dest.allowSquashing();
+
         if (!hasMultipleLayouts()) {
             dest.writeInt(MODE_NORMAL);
             // We only write the bitmap cache if we are the root RemoteViews, as this cache
@@ -6035,12 +6113,7 @@
             if (mIsRoot) {
                 mBitmapCache.writeBitmapsToParcel(dest, flags);
             }
-            if (!mIsRoot && (flags & PARCELABLE_ELIDE_DUPLICATES) != 0) {
-                dest.writeInt(0);
-            } else {
-                dest.writeInt(1);
-                mApplication.writeToParcel(dest, flags);
-            }
+            mApplication.writeToParcel(dest, flags);
             if (mIsRoot || mIdealSize == null) {
                 dest.writeInt(0);
             } else {
@@ -6050,17 +6123,15 @@
             dest.writeInt(mLayoutId);
             dest.writeInt(mViewId);
             dest.writeInt(mLightBackgroundLayoutId);
-            writeActionsToParcel(dest);
+            writeActionsToParcel(dest, flags);
         } else if (hasSizedRemoteViews()) {
             dest.writeInt(MODE_HAS_SIZED_REMOTEVIEWS);
             if (mIsRoot) {
                 mBitmapCache.writeBitmapsToParcel(dest, flags);
             }
-            int childFlags = flags;
             dest.writeInt(mSizedRemoteViews.size());
             for (RemoteViews view : mSizedRemoteViews) {
-                view.writeToParcel(dest, childFlags);
-                childFlags |= PARCELABLE_ELIDE_DUPLICATES;
+                view.writeToParcel(dest, flags);
             }
         } else {
             dest.writeInt(MODE_HAS_LANDSCAPE_AND_PORTRAIT);
@@ -6071,13 +6142,15 @@
             }
             mLandscape.writeToParcel(dest, flags);
             // Both RemoteViews already share the same package and user
-            mPortrait.writeToParcel(dest, flags | PARCELABLE_ELIDE_DUPLICATES);
+            mPortrait.writeToParcel(dest, flags);
         }
         dest.writeInt(mApplyFlags);
         dest.writeLong(mProviderInstanceId);
+
+        dest.restoreAllowSquashing(prevSquashingAllowed);
     }
 
-    private void writeActionsToParcel(Parcel parcel) {
+    private void writeActionsToParcel(Parcel parcel, int flags) {
         int count;
         if (mActions != null) {
             count = mActions.size();
@@ -6088,8 +6161,7 @@
         for (int i = 0; i < count; i++) {
             Action a = mActions.get(i);
             parcel.writeInt(a.getActionTag());
-            a.writeToParcel(parcel, a.hasSameAppInfo(mApplication)
-                    ? PARCELABLE_ELIDE_DUPLICATES : 0);
+            a.writeToParcel(parcel, flags);
         }
     }
 
@@ -6568,6 +6640,8 @@
         private final boolean mHasStableIds;
         private final int mViewTypeCount;
 
+        private HierarchyRootData mHierarchyRootData;
+
         RemoteCollectionItems(
                 long[] ids, RemoteViews[] views, boolean hasStableIds, int viewTypeCount) {
             mIds = ids;
@@ -6590,16 +6664,53 @@
                         "View type count is set to " + viewTypeCount + ", but the collection "
                                 + "contains " + layoutIdCount + " different layout ids");
             }
+
+            // Until the collection items are attached to a parent, we configure the first item
+            // to be the root of the others to share caches and save space during serialization.
+            if (views.length > 0) {
+                setHierarchyRootData(views[0].getHierarchyRootData());
+                views[0].mIsRoot = true;
+            }
         }
 
-        RemoteCollectionItems(Parcel in) {
+        RemoteCollectionItems(@NonNull Parcel in, @Nullable HierarchyRootData hierarchyRootData) {
+            mHasStableIds = in.readBoolean();
+            mViewTypeCount = in.readInt();
             int length = in.readInt();
             mIds = new long[length];
             in.readLongArray(mIds);
+
+            boolean attached = in.readBoolean();
             mViews = new RemoteViews[length];
-            in.readTypedArray(mViews, RemoteViews.CREATOR);
-            mHasStableIds = in.readBoolean();
-            mViewTypeCount = in.readInt();
+            int firstChildIndex;
+            if (attached) {
+                if (hierarchyRootData == null) {
+                    throw new IllegalStateException("Cannot unparcel a RemoteCollectionItems that "
+                            + "was parceled as attached without providing data for a root "
+                            + "RemoteViews");
+                }
+                mHierarchyRootData = hierarchyRootData;
+                firstChildIndex = 0;
+            } else {
+                mViews[0] = new RemoteViews(in);
+                mHierarchyRootData = mViews[0].getHierarchyRootData();
+                firstChildIndex = 1;
+            }
+
+            for (int i = firstChildIndex; i < length; i++) {
+                mViews[i] = new RemoteViews(
+                        in,
+                        mHierarchyRootData,
+                        /* info= */ null,
+                        /* depth= */ 0);
+            }
+        }
+
+        void setHierarchyRootData(@NonNull HierarchyRootData rootData) {
+            mHierarchyRootData = rootData;
+            for (RemoteViews view : mViews) {
+                view.configureAsChild(rootData);
+            }
         }
 
         @Override
@@ -6609,11 +6720,39 @@
 
         @Override
         public void writeToParcel(@NonNull Parcel dest, int flags) {
-            dest.writeInt(mIds.length);
-            dest.writeLongArray(mIds);
-            dest.writeTypedArray(mViews, flags);
+            writeToParcel(dest, flags, /* attached= */ false);
+        }
+
+        private void writeToParcel(@NonNull Parcel dest, int flags, boolean attached) {
+            boolean prevAllowSquashing = dest.allowSquashing();
+
             dest.writeBoolean(mHasStableIds);
             dest.writeInt(mViewTypeCount);
+            dest.writeInt(mIds.length);
+            dest.writeLongArray(mIds);
+
+            if (attached && mHierarchyRootData == null) {
+                throw new IllegalStateException("Cannot call writeToParcelAttached for a "
+                        + "RemoteCollectionItems without first calling setHierarchyRootData()");
+            }
+
+            // Write whether we parceled as attached or not. This allows cleaner validation and
+            // proper error messaging when unparceling later.
+            dest.writeBoolean(attached);
+            boolean restoreRoot = false;
+            if (!attached && mViews.length > 0 && !mViews[0].mIsRoot) {
+                // If we're writing unattached, temporarily set the first item as the root so that
+                // the bitmap cache is written to the parcel.
+                restoreRoot = true;
+                mViews[0].mIsRoot = true;
+            }
+
+            for (RemoteViews view : mViews) {
+                view.writeToParcel(dest, flags);
+            }
+
+            if (restoreRoot) mViews[0].mIsRoot = false;
+            dest.restoreAllowSquashing(prevAllowSquashing);
         }
 
         /**
@@ -6671,7 +6810,7 @@
             @NonNull
             @Override
             public RemoteCollectionItems createFromParcel(@NonNull Parcel source) {
-                return new RemoteCollectionItems(source);
+                return new RemoteCollectionItems(source, /* hierarchyRoot= */ null);
             }
 
             @NonNull
@@ -6846,4 +6985,29 @@
         viewId |= childId;
         return viewId;
     }
+
+    @Nullable
+    private static Pair<String, Integer> getPackageUserKey(@Nullable ApplicationInfo info) {
+        if (info == null || info.packageName ==  null) return null;
+        return Pair.create(info.packageName, info.uid);
+    }
+
+    private HierarchyRootData getHierarchyRootData() {
+        return new HierarchyRootData(mBitmapCache, mApplicationInfoCache, mClassCookies);
+    }
+
+    private static final class HierarchyRootData {
+        final BitmapCache mBitmapCache;
+        final ApplicationInfoCache mApplicationInfoCache;
+        final Map<Class, Object> mClassCookies;
+
+        HierarchyRootData(
+                BitmapCache bitmapCache,
+                ApplicationInfoCache applicationInfoCache,
+                Map<Class, Object> classCookies) {
+            mBitmapCache = bitmapCache;
+            mApplicationInfoCache = applicationInfoCache;
+            mClassCookies = classCookies;
+        }
+    }
 }
diff --git a/core/java/android/widget/RemoteViewsListAdapter.java b/core/java/android/widget/RemoteViewsListAdapter.java
index 827d033..46f80f3 100644
--- a/core/java/android/widget/RemoteViewsListAdapter.java
+++ b/core/java/android/widget/RemoteViewsListAdapter.java
@@ -89,8 +89,7 @@
             RemoteViews rv = mRemoteViewsList.get(position);
             rv.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD);
             View v;
-            if (convertView != null && rv != null &&
-                    convertView.getId() == rv.getLayoutId()) {
+            if (convertView != null && convertView.getId() == rv.getLayoutId()) {
                 v = convertView;
                 rv.reapply(mContext, v, null /* handler */, null /* size */, mColorResources);
             } else {
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 6b3a698..c532557 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -20,6 +20,7 @@
 import android.text.Editable;
 import android.text.Selection;
 import android.text.Spanned;
+import android.text.SpannedString;
 import android.text.method.WordIterator;
 import android.text.style.SpellCheckSpan;
 import android.text.style.SuggestionSpan;
@@ -416,7 +417,15 @@
                     }
                     if (spellCheckSpanStart >= 0 && spellCheckSpanEnd > spellCheckSpanStart
                             && end > start) {
-                        removeErrorSuggestionSpan(editable, start, end, RemoveReason.OBSOLETE);
+                        boolean visibleToAccessibility = mTextView.isVisibleToAccessibility();
+                        CharSequence beforeText =
+                                visibleToAccessibility ? new SpannedString(editable) : null;
+                        boolean spanRemoved = removeErrorSuggestionSpan(
+                                editable, start, end, RemoveReason.OBSOLETE);
+                        if (visibleToAccessibility && spanRemoved) {
+                            mTextView.sendAccessibilityEventTypeViewTextChanged(
+                                    beforeText, start, end);
+                        }
                     }
                 }
                 return spellCheckSpan;
@@ -437,8 +446,9 @@
         OBSOLETE,
     }
 
-    private static void removeErrorSuggestionSpan(
+    private static boolean removeErrorSuggestionSpan(
             Editable editable, int start, int end, RemoveReason reason) {
+        boolean spanRemoved = false;
         SuggestionSpan[] spans = editable.getSpans(start, end, SuggestionSpan.class);
         for (SuggestionSpan span : spans) {
             if (editable.getSpanStart(span) == start
@@ -450,8 +460,10 @@
                             + editable.subSequence(start, end) + ", reason: " + reason);
                 }
                 editable.removeSpan(span);
+                spanRemoved = true;
             }
         }
+        return spanRemoved;
     }
 
     @Override
@@ -568,8 +580,13 @@
         }
         SuggestionSpan suggestionSpan =
                 new SuggestionSpan(mTextView.getContext(), suggestions, flags);
-        removeErrorSuggestionSpan(editable, start, end, RemoveReason.REPLACE);
+        boolean spanRemoved = removeErrorSuggestionSpan(editable, start, end, RemoveReason.REPLACE);
+        boolean sendAccessibilityEvent = !spanRemoved && mTextView.isVisibleToAccessibility();
+        CharSequence beforeText = sendAccessibilityEvent ? new SpannedString(editable) : null;
         editable.setSpan(suggestionSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
+        if (sendAccessibilityEvent) {
+            mTextView.sendAccessibilityEventTypeViewTextChanged(beforeText, start, end);
+        }
 
         mTextView.invalidateRegion(start, end, false /* No cursor involved */);
     }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 8fba583..496fa67 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -12501,6 +12501,11 @@
         return TextUtils.trimToParcelableSize(mTransformed);
     }
 
+    boolean isVisibleToAccessibility() {
+        return AccessibilityManager.getInstance(mContext).isEnabled()
+                && (isFocused() || (isSelected() && isShown()));
+    }
+
     void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText,
             int fromIndex, int removedCount, int addedCount) {
         AccessibilityEvent event =
@@ -12512,6 +12517,16 @@
         sendAccessibilityEventUnchecked(event);
     }
 
+    void sendAccessibilityEventTypeViewTextChanged(CharSequence beforeText,
+            int fromIndex, int toIndex) {
+        AccessibilityEvent event =
+                AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
+        event.setFromIndex(fromIndex);
+        event.setToIndex(toIndex);
+        event.setBeforeText(beforeText);
+        sendAccessibilityEventUnchecked(event);
+    }
+
     private InputMethodManager getInputMethodManager() {
         return getContext().getSystemService(InputMethodManager.class);
     }
@@ -13826,10 +13841,9 @@
             }
             TextView.this.handleTextChanged(buffer, start, before, after);
 
-            if (AccessibilityManager.getInstance(mContext).isEnabled()
-                    && (isFocused() || (isSelected() && isShown()))) {
+            if (isVisibleToAccessibility()) {
                 sendAccessibilityEventTypeViewTextChanged(mBeforeText, start, before, after);
-                mBeforeText = TextUtils.stringOrSpannedString(mTransformed);
+                mBeforeText = null;
             }
         }
 
@@ -13857,54 +13871,6 @@
                 Log.v(LOG_TAG, "onSpanAdded s=" + s + " e=" + e + " what=" + what + ": " + buf);
             }
             TextView.this.spanChange(buf, what, -1, s, -1, e);
-            // Note we don't update mBeforeText here. We look for SuggestionSpans added after the
-            // text content changes.
-            if (AccessibilityManager.getInstance(mContext).isEnabled()
-                    && (isFocused() || (isSelected() && isShown()))
-                    && (what instanceof SuggestionSpan)) {
-                // When the user types a new word, and SuggestionSpans on the existing words will be
-                // removed and added again. We don't need to send out events for existing
-                // SuggestionSpans. Multiple spans can be placed on the range.
-                if (mBeforeText instanceof SpannedString) {
-                    final SpannedString beforeSpannedString = (SpannedString) mBeforeText;
-                    if ((beforeSpannedString.getSpanStart(what) == s)
-                            && (beforeSpannedString.getSpanEnd(what) == e)) {
-                        // Exactly same span is found.
-                        return;
-                    }
-                    // Suggestion span couldn't be found. Try to find a suggestion span that has the
-                    // same contents.
-                    SuggestionSpan[] suggestionSpans = beforeSpannedString.getSpans(s, e,
-                            SuggestionSpan.class);
-                    for (final SuggestionSpan suggestionSpan : suggestionSpans) {
-                        final int start = beforeSpannedString.getSpanStart(suggestionSpan);
-                        if (start != s) {
-                            continue;
-                        }
-                        final int end = beforeSpannedString.getSpanEnd(suggestionSpan);
-                        if (end != e) {
-                            continue;
-                        }
-                        if (equalSuggestionSpan(suggestionSpan, (SuggestionSpan) what)) {
-                            return;
-                        }
-                    }
-                }
-                AccessibilityEvent event =
-                        AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
-                event.setFromIndex(s);
-                event.setToIndex(e);
-                event.setBeforeText(mBeforeText);
-                sendAccessibilityEventUnchecked(event);
-            }
-        }
-
-        private boolean equalSuggestionSpan(SuggestionSpan span1, SuggestionSpan span2) {
-            // We compare flags because flags will determine the underline color.
-            return Arrays.equals(span1.getSuggestions(), span2.getSuggestions())
-                    && Objects.equals(span1.getLocaleObject(), span2.getLocaleObject())
-                    && span1.getLocale().equals(span2.getLocale())
-                    && (span1.getFlags() == span2.getFlags());
         }
 
         public void onSpanRemoved(Spannable buf, Object what, int s, int e) {
diff --git a/core/java/android/window/DisplayAreaOrganizer.java b/core/java/android/window/DisplayAreaOrganizer.java
index 6758a3b..974a1dd 100644
--- a/core/java/android/window/DisplayAreaOrganizer.java
+++ b/core/java/android/window/DisplayAreaOrganizer.java
@@ -109,6 +109,18 @@
     public static final int FEATURE_ONE_HANDED_BACKGROUND_PANEL = FEATURE_SYSTEM_FIRST + 8;
 
     /**
+     * Display area hosting IME window tokens (@see ImeContainer). By default, IMEs are parented
+     * to FEATURE_IME_PLACEHOLDER but can be reparented under other RootDisplayArea.
+     *
+     * This feature can register organizers in order to disable the reparenting logic and manage
+     * the position and settings of the container manually. This is useful for foldable devices
+     * which require custom UX rules for the IME position (e.g. IME on one screen and the focused
+     * app on another screen).
+     * @hide
+     */
+    public static final int FEATURE_IME = FEATURE_SYSTEM_FIRST + 9;
+
+    /**
      * The last boundary of display area for system features
      */
     public static final int FEATURE_SYSTEM_LAST = 10_000;
diff --git a/core/java/android/window/DisplayWindowPolicyController.java b/core/java/android/window/DisplayWindowPolicyController.java
new file mode 100644
index 0000000..7677b89
--- /dev/null
+++ b/core/java/android/window/DisplayWindowPolicyController.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2021 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 android.window;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
+
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Abstract class to control the policies of the windows that can be displayed on the virtual
+ * display.
+ *
+ * @hide
+ */
+public abstract class DisplayWindowPolicyController {
+    /**
+     * The window flags that we are interested in.
+     * @see android.view.WindowManager.LayoutParams
+     * @see #keepActivityOnWindowFlagsChanged
+     */
+    private int mWindowFlags;
+
+    /**
+     * Returns {@code true} if the given window flags contain the flags that we're interested in.
+     */
+    public final boolean isInterestedWindowFlags(int windowFlags) {
+        return (mWindowFlags & windowFlags) != 0;
+    }
+
+    /**
+     * Sets the window flags that we’re interested in and expected
+     * #keepActivityOnWindowFlagsChanged to be called if any changes.
+     */
+    public final void setInterestedWindowFlags(int windowFlags) {
+        mWindowFlags = windowFlags;
+    }
+
+    /**
+     * Returns {@code true} if the given activities can be displayed on this virtual display.
+     */
+    public abstract boolean canContainActivities(@NonNull List<ActivityInfo> activities);
+
+    /**
+     * Called when an Activity window is layouted with the new changes where contains the
+     * window flags that we’re interested in.
+     * Returns {@code false} if the Activity cannot remain on the display and the activity task will
+     * be moved back to default display.
+     */
+    public abstract boolean keepActivityOnWindowFlagsChanged(
+            ActivityInfo activityInfo, int windowFlags);
+
+    /**
+     * This is called when the top activity of the display is changed.
+     */
+    public void onTopActivityChanged(ComponentName topActivity, int uid) {}
+
+    /**
+     * This is called when the apps that contains running activities on the display has changed.
+     */
+    public void onRunningAppsChanged(int[] runningUids) {}
+
+    /** Dump debug data */
+    public void dump(String prefix, final PrintWriter pw) {
+        pw.println(prefix + "DisplayWindowPolicyController{" + super.toString() + "}");
+        pw.println(prefix + "  mWindowFlags=" + mWindowFlags);
+    }
+}
diff --git a/core/java/android/window/ITaskFragmentOrganizer.aidl b/core/java/android/window/ITaskFragmentOrganizer.aidl
index 5eb432e..cdfa206 100644
--- a/core/java/android/window/ITaskFragmentOrganizer.aidl
+++ b/core/java/android/window/ITaskFragmentOrganizer.aidl
@@ -19,12 +19,11 @@
 import android.content.res.Configuration;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.window.TaskFragmentAppearedInfo;
 import android.window.TaskFragmentInfo;
 
 /** @hide */
 oneway interface ITaskFragmentOrganizer {
-    void onTaskFragmentAppeared(in TaskFragmentAppearedInfo taskFragmentAppearedInfo);
+    void onTaskFragmentAppeared(in TaskFragmentInfo taskFragmentInfo);
     void onTaskFragmentInfoChanged(in TaskFragmentInfo taskFragmentInfo);
     void onTaskFragmentVanished(in TaskFragmentInfo taskFragmentInfo);
 
diff --git a/core/java/android/window/TaskFragmentAppearedInfo.java b/core/java/android/window/TaskFragmentAppearedInfo.java
deleted file mode 100644
index 89d9a95..0000000
--- a/core/java/android/window/TaskFragmentAppearedInfo.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2021 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 android.window;
-
-import android.annotation.NonNull;
-import android.annotation.TestApi;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.view.SurfaceControl;
-
-/**
- * Data object for the TaskFragment info provided when a TaskFragment is presented to an organizer.
- * @hide
- */
-@TestApi
-public final class TaskFragmentAppearedInfo implements Parcelable {
-
-    @NonNull
-    private final TaskFragmentInfo mTaskFragmentInfo;
-
-    @NonNull
-    private final SurfaceControl mLeash;
-
-    /** @hide */
-    public TaskFragmentAppearedInfo(
-            @NonNull TaskFragmentInfo taskFragmentInfo, @NonNull SurfaceControl leash) {
-        mTaskFragmentInfo = taskFragmentInfo;
-        mLeash = leash;
-    }
-
-    @NonNull
-    public TaskFragmentInfo getTaskFragmentInfo() {
-        return mTaskFragmentInfo;
-    }
-
-    @NonNull
-    public SurfaceControl getLeash() {
-        return mLeash;
-    }
-
-    private TaskFragmentAppearedInfo(Parcel in) {
-        mTaskFragmentInfo = in.readTypedObject(TaskFragmentInfo.CREATOR);
-        mLeash = in.readTypedObject(SurfaceControl.CREATOR);
-    }
-
-    /** @hide */
-    @Override
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeTypedObject(mTaskFragmentInfo, flags);
-        dest.writeTypedObject(mLeash, flags);
-    }
-
-    @NonNull
-    public static final Creator<TaskFragmentAppearedInfo> CREATOR =
-            new Creator<TaskFragmentAppearedInfo>() {
-                @Override
-                public TaskFragmentAppearedInfo createFromParcel(Parcel in) {
-                    return new TaskFragmentAppearedInfo(in);
-                }
-
-                @Override
-                public TaskFragmentAppearedInfo[] newArray(int size) {
-                    return new TaskFragmentAppearedInfo[size];
-                }
-            };
-
-    @Override
-    public String toString() {
-        return "TaskFragmentAppearedInfo{"
-                + " taskFragmentInfo=" + mTaskFragmentInfo
-                + "}";
-    }
-
-    /** @hide */
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-}
diff --git a/core/java/android/window/TaskFragmentOrganizer.java b/core/java/android/window/TaskFragmentOrganizer.java
index 337c5a1..7e7d370 100644
--- a/core/java/android/window/TaskFragmentOrganizer.java
+++ b/core/java/android/window/TaskFragmentOrganizer.java
@@ -120,8 +120,7 @@
     }
 
     /** Called when a TaskFragment is created and organized by this organizer. */
-    public void onTaskFragmentAppeared(
-            @NonNull TaskFragmentAppearedInfo taskFragmentAppearedInfo) {}
+    public void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo) {}
 
     /** Called when the status of an organized TaskFragment is changed. */
     public void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo) {}
@@ -169,7 +168,7 @@
 
     private final ITaskFragmentOrganizer mInterface = new ITaskFragmentOrganizer.Stub() {
         @Override
-        public void onTaskFragmentAppeared(@NonNull TaskFragmentAppearedInfo taskFragmentInfo) {
+        public void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo) {
             mExecutor.execute(
                     () -> TaskFragmentOrganizer.this.onTaskFragmentAppeared(taskFragmentInfo));
         }
diff --git a/core/java/android/window/WindowContextController.java b/core/java/android/window/WindowContextController.java
index 5aa6233..17b675f 100644
--- a/core/java/android/window/WindowContextController.java
+++ b/core/java/android/window/WindowContextController.java
@@ -19,13 +19,10 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.os.Bundle;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.view.IWindowManager;
 import android.view.WindowManager.LayoutParams.WindowType;
-import android.view.WindowManagerGlobal;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -38,7 +35,6 @@
  * @hide
  */
 public class WindowContextController {
-    private final IWindowManager mWms;
     /**
      * {@code true} to indicate that the {@code mToken} is associated with a
      * {@link com.android.server.wm.DisplayArea}. Note that {@code mToken} is able to attach a
@@ -56,14 +52,7 @@
      *              {@link Context#getWindowContextToken()}.
      */
     public WindowContextController(@NonNull WindowTokenClient token) {
-        this(token, WindowManagerGlobal.getWindowManagerService());
-    }
-
-    /** Used for test only. DO NOT USE it in production code. */
-    @VisibleForTesting
-    public WindowContextController(@NonNull WindowTokenClient token, IWindowManager mockWms) {
         mToken = token;
-        mWms = mockWms;
     }
 
     /**
@@ -80,19 +69,7 @@
             throw new IllegalStateException("A Window Context can be only attached to "
                     + "a DisplayArea once.");
         }
-        try {
-            final Configuration configuration = mWms.attachWindowContextToDisplayArea(mToken, type,
-                    displayId, options);
-            if (configuration != null) {
-                mAttachedToDisplayArea = true;
-                // Send the DisplayArea's configuration to WindowContext directly instead of
-                // waiting for dispatching from WMS.
-                mToken.onConfigurationChanged(configuration, displayId,
-                        false /* shouldReportConfigChange */);
-            }
-        }  catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        mAttachedToDisplayArea = mToken.attachToDisplayArea(type, displayId, options);
     }
 
     /**
@@ -120,22 +97,14 @@
             throw new IllegalStateException("The Window Context should have been attached"
                     + " to a DisplayArea.");
         }
-        try {
-            mWms.attachWindowContextToWindowToken(mToken, windowToken);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        mToken.attachToWindowToken(windowToken);
     }
 
     /** Detaches the window context from the node it's currently associated with. */
     public void detachIfNeeded() {
         if (mAttachedToDisplayArea) {
-            try {
-                mWms.detachWindowContextFromWindowContainer(mToken);
-                mAttachedToDisplayArea = false;
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+            mToken.detachFromWindowContainerIfNeeded();
+            mAttachedToDisplayArea = false;
         }
     }
 }
diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java
index f3e3859..b331a9e 100644
--- a/core/java/android/window/WindowTokenClient.java
+++ b/core/java/android/window/WindowTokenClient.java
@@ -21,6 +21,7 @@
 import static android.window.ConfigurationHelper.shouldUpdateResources;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityThread;
 import android.app.IWindowToken;
 import android.app.ResourcesManager;
@@ -31,7 +32,11 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.IBinder;
+import android.os.RemoteException;
 import android.util.Log;
+import android.view.IWindowManager;
+import android.view.WindowManager.LayoutParams.WindowType;
+import android.view.WindowManagerGlobal;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -59,10 +64,14 @@
 
     private final ResourcesManager mResourcesManager = ResourcesManager.getInstance();
 
+    private IWindowManager mWms;
+
     private final Configuration mConfiguration = new Configuration();
 
     private boolean mShouldDumpConfigForIme;
 
+    private boolean mAttachToWindowContainer;
+
     /**
      * Attaches {@code context} to this {@link WindowTokenClient}. Each {@link WindowTokenClient}
      * can only attach one {@link Context}.
@@ -84,6 +93,88 @@
     }
 
     /**
+     * Attaches this {@link WindowTokenClient} to a {@link com.android.server.wm.DisplayArea}.
+     *
+     * @param type The window type of the {@link WindowContext}
+     * @param displayId The {@link Context#getDisplayId() ID of display} to associate with
+     * @param options The window context launched option
+     * @return {@code true} if attaching successfully.
+     */
+    public boolean attachToDisplayArea(@WindowType int type, int displayId,
+            @Nullable Bundle options) {
+        try {
+            final Configuration configuration = getWindowManagerService()
+                    .attachWindowContextToDisplayArea(this, type, displayId, options);
+            if (configuration == null) {
+                return false;
+            }
+            onConfigurationChanged(configuration, displayId, false /* shouldReportConfigChange */);
+            mAttachToWindowContainer = true;
+            return true;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Attaches this {@link WindowTokenClient} to a {@code DisplayContent}.
+     *
+     * @param displayId The {@link Context#getDisplayId() ID of display} to associate with
+     * @return {@code true} if attaching successfully.
+     */
+    public boolean attachToDisplayContent(int displayId) {
+        final IWindowManager wms = getWindowManagerService();
+        // #createSystemUiContext may call this method before WindowManagerService is initialized.
+        if (wms == null) {
+            return false;
+        }
+        try {
+            final Configuration configuration = wms.attachToDisplayContent(this, displayId);
+            if (configuration == null) {
+                return false;
+            }
+            onConfigurationChanged(configuration, displayId, false /* shouldReportConfigChange */);
+            mAttachToWindowContainer = true;
+            return true;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Attaches this {@link WindowTokenClient} to a {@code windowToken}.
+     *
+     * @param windowToken the window token to associated with
+     */
+    public void attachToWindowToken(IBinder windowToken) {
+        try {
+            getWindowManagerService().attachWindowContextToWindowToken(this, windowToken);
+            mAttachToWindowContainer = true;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** Detaches this {@link WindowTokenClient} from associated WindowContainer if there's one. */
+    public void detachFromWindowContainerIfNeeded() {
+        if (!mAttachToWindowContainer) {
+            return;
+        }
+        try {
+            getWindowManagerService().detachWindowContextFromWindowContainer(this);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    private IWindowManager getWindowManagerService() {
+        if (mWms == null) {
+            mWms = WindowManagerGlobal.getWindowManagerService();
+        }
+        return mWms;
+    }
+
+    /**
      * Called when {@link Configuration} updates from the server side receive.
      *
      * @param newConfig the updated {@link Configuration}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 9b1bef06..359c382 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -28,6 +28,7 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityManager;
+import android.app.ActivityTaskManager;
 import android.app.SharedElementCallback;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppPredictionManager;
@@ -70,9 +71,11 @@
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Message;
 import android.os.Parcelable;
 import android.os.PatternMatcher;
+import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -151,6 +154,19 @@
         ChooserListAdapter.ChooserListCommunicator,
         SelectableTargetInfoCommunicator {
     private static final String TAG = "ChooserActivity";
+
+    /**
+     * Whether this chooser is operating in "headless springboard" mode (as determined during
+     * onCreate). In this mode, our activity sits in the background and waits for the new
+     * "unbundled" chooser to handle the Sharesheet experience; the system ChooserActivity is
+     * responsible only for providing the startActivityAsCaller permission token and keeping it
+     * valid for the life of the unbundled delegate activity.
+     *
+     * TODO: when the unbundled chooser is fully launched, the system-side "springboard" can use a
+     * simpler implementation that doesn't inherit from ResolverActivity.
+     */
+    private boolean mIsHeadlessSpringboardActivity;
+
     private AppPredictor mPersonalAppPredictor;
     private AppPredictor mWorkAppPredictor;
     private boolean mShouldDisplayLandscape;
@@ -170,6 +186,17 @@
             = "com.android.internal.app.ChooserActivity.EXTRA_PRIVATE_RETAIN_IN_ON_STOP";
 
     /**
+     * Boolean extra added to "unbundled Sharesheet" delegation intents to signal whether the app
+     * prediction service is available. Our query of the service <em>availability</em> depends on
+     * privileges that are only available in the system, even though the service itself would then
+     * be available to the unbundled component. For now, we just include the query result as part of
+     * the handover intent.
+     * TODO: investigate whether the privileged query is necessary to determine the availability.
+     */
+    protected static final String EXTRA_IS_APP_PREDICTION_SERVICE_AVAILABLE =
+            "com.android.internal.app.ChooserActivity.EXTRA_IS_APP_PREDICTION_SERVICE_AVAILABLE";
+
+    /**
      * Transition name for the first image preview.
      * To be used for shared element transition into this activity.
      * @hide
@@ -235,6 +262,11 @@
 
     private static final float DIRECT_SHARE_EXPANSION_RATE = 0.78f;
 
+    private boolean mEnableChooserDelegate =
+            DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+                    SystemUiDeviceConfigFlags.USE_DELEGATE_CHOOSER,
+                    false);
+
     private static final int DEFAULT_SALT_EXPIRATION_DAYS = 7;
     private int mMaxHashSaltDays = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
             SystemUiDeviceConfigFlags.HASH_SALT_MAX_DAYS,
@@ -500,6 +532,12 @@
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
+        if (handOverToDelegateChooser()) {
+            super_onCreate(savedInstanceState);
+            mIsHeadlessSpringboardActivity = true;
+            return;
+        }
+
         final long intentReceivedTime = System.currentTimeMillis();
         getChooserActivityLogger().logSharesheetTriggered();
         // This is the only place this value is being set. Effectively final.
@@ -714,6 +752,69 @@
         postponeEnterTransition();
     }
 
+    private boolean handOverToDelegateChooser() {
+        // Check the explicit classname so that we don't interfere with the flow of any subclasses.
+        if (!this.getClass().getName().equals("com.android.internal.app.ChooserActivity")
+                || !mEnableChooserDelegate) {
+            return false;
+        }
+
+        try {
+            IBinder permissionToken = ActivityTaskManager.getService()
+                    .requestStartActivityPermissionToken(getActivityToken());
+            Intent delegationIntent = new Intent();
+            final ComponentName delegateActivity = ComponentName.unflattenFromString(
+                    Resources.getSystem().getString(R.string.config_chooserActivity));
+            delegationIntent.setComponent(delegateActivity);
+            delegationIntent.putExtra(Intent.EXTRA_INTENT, getIntent());
+            delegationIntent.putExtra(ActivityTaskManager.EXTRA_PERMISSION_TOKEN, permissionToken);
+
+            // Query prediction availability; mIsAppPredictorComponentAvailable isn't initialized.
+            delegationIntent.putExtra(
+                    EXTRA_IS_APP_PREDICTION_SERVICE_AVAILABLE, isAppPredictionServiceAvailable());
+
+            delegationIntent.addFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
+
+            // Don't close until the delegate finishes, or the token will be invalidated.
+            mAwaitingDelegateResponse = true;
+            startActivityForResult(delegationIntent, REQUEST_CODE_RETURN_FROM_DELEGATE_CHOOSER);
+            return true;
+        } catch (RemoteException e) {
+            Log.e(TAG, e.toString());
+        }
+        return false;
+    }
+
+    @Override
+    protected void onRestart() {
+        if (mIsHeadlessSpringboardActivity) {
+            super_onRestart();
+            return;
+        }
+
+        super.onRestart();
+    }
+
+    @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        if (mIsHeadlessSpringboardActivity) {
+            super_onSaveInstanceState(outState);
+            return;
+        }
+
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
+    protected void onRestoreInstanceState(Bundle savedInstanceState) {
+        if (mIsHeadlessSpringboardActivity) {
+            super_onRestoreInstanceState(savedInstanceState);
+            return;
+        }
+
+        super.onRestoreInstanceState(savedInstanceState);
+    }
+
     @Override
     protected int appliedThemeResId() {
         return R.style.Theme_DeviceDefault_Chooser;
@@ -886,7 +987,8 @@
             return false;
         }
 
-        // Check if the app prediction component actually exists on the device.
+        // Check if the app prediction component actually exists on the device. The component is
+        // only visible when this is running in a system activity; otherwise this check will fail.
         Intent intent = new Intent();
         intent.setComponent(appPredictionComponentName);
         if (getPackageManager().resolveService(intent, PackageManager.MATCH_ALL) == null) {
@@ -998,6 +1100,11 @@
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
+        if (mIsHeadlessSpringboardActivity) {
+            super_onConfigurationChanged(newConfig);
+            return;
+        }
+
         super.onConfigurationChanged(newConfig);
         ViewPager viewPager = findViewById(R.id.profile_pager);
         if (viewPager.isLayoutRtl()) {
@@ -1543,6 +1650,11 @@
     @Override
     protected void onDestroy() {
         super.onDestroy();
+
+        if (mIsHeadlessSpringboardActivity) {
+            return;
+        }
+
         if (mRefinementResultReceiver != null) {
             mRefinementResultReceiver.destroy();
             mRefinementResultReceiver = null;
diff --git a/core/java/com/android/internal/app/ConfirmUserCreationActivity.java b/core/java/com/android/internal/app/ConfirmUserCreationActivity.java
index 0047f43..ee4d46d 100644
--- a/core/java/com/android/internal/app/ConfirmUserCreationActivity.java
+++ b/core/java/com/android/internal/app/ConfirmUserCreationActivity.java
@@ -23,12 +23,10 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.UserInfo;
 import android.os.Bundle;
 import android.os.PersistableBundle;
-import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Log;
 
@@ -44,6 +42,8 @@
 
     private static final String TAG = "CreateUser";
 
+    private static final String USER_TYPE = UserManager.USER_TYPE_FULL_SECONDARY;
+
     private String mUserName;
     private String mAccountName;
     private String mAccountType;
@@ -103,7 +103,7 @@
         boolean cantCreateUser = mUserManager.hasUserRestriction(UserManager.DISALLOW_ADD_USER)
                 || !mUserManager.isAdminUser();
         // Check the system state and user count
-        boolean cantCreateAnyMoreUsers = !mUserManager.canAddMoreUsers();
+        boolean cantCreateAnyMoreUsers = !mUserManager.canAddMoreUsers(USER_TYPE);
         // Check the account existence
         final Account account = new Account(mAccountName, mAccountType);
         boolean accountExists = mAccountName != null && mAccountType != null
@@ -130,7 +130,7 @@
         setResult(RESULT_CANCELED);
         if (which == BUTTON_POSITIVE && mCanProceed) {
             Log.i(TAG, "Ok, creating user");
-            UserInfo user = mUserManager.createUser(mUserName, 0);
+            UserInfo user = mUserManager.createUser(mUserName, USER_TYPE, 0);
             if (user == null) {
                 Log.e(TAG, "Couldn't create user");
                 finish();
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 9af4f91..fd8637a 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -152,7 +152,7 @@
     /** See {@link #setRetainInOnStop}. */
     private boolean mRetainInOnStop;
 
-    private static final int REQUEST_CODE_RETURN_FROM_DELEGATE_CHOOSER = 20;
+    protected static final int REQUEST_CODE_RETURN_FROM_DELEGATE_CHOOSER = 20;
 
     private static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args";
     private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
@@ -323,6 +323,86 @@
         super.onCreate(savedInstanceState);
     }
 
+    /**
+     * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
+     * where we hand over to the unbundled chooser (while violating many of the invariants of a
+     * typical ResolverActivity implementation). Subclasses running in this mode need to be able
+     * to opt-out of the normal ResolverActivity behavior.
+     *
+     * TODO: this should be removed later on in the unbundling migration, when the springboard
+     * activity no longer needs to derive from ResolverActivity. The hold-over design here is
+     * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
+     * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
+     * implementations that depend on the invariants that are violated in the headless mode). If
+     * necessary, we could instead consider using a springboard-only activity on the system side
+     * immediately, which would delegate either to the unbundled chooser, or to a
+     * (properly-inheriting) system ChooserActivity. This would have performance implications even
+     * when the unbundling experiment is disabled.
+     */
+    protected void super_onRestart() {
+        super.onRestart();
+    }
+
+    /**
+     * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
+     * where we hand over to the unbundled chooser (while violating many of the invariants of a
+     * typical ResolverActivity implementation). Subclasses running in this mode need to be able
+     * to opt-out of the normal ResolverActivity behavior.
+     *
+     * TODO: this should be removed later on in the unbundling migration, when the springboard
+     * activity no longer needs to derive from ResolverActivity. The hold-over design here is
+     * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
+     * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
+     * implementations that depend on the invariants that are violated in the headless mode). If
+     * necessary, we could instead consider using a springboard-only activity on the system side
+     * immediately, which would delegate either to the unbundled chooser, or to a
+     * (properly-inheriting) system ChooserActivity. This would have performance implications even
+     * when the unbundling experiment is disabled.
+     */
+    protected void super_onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+    }
+
+    /**
+     * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
+     * where we hand over to the unbundled chooser (while violating many of the invariants of a
+     * typical ResolverActivity implementation). Subclasses running in this mode need to be able
+     * to opt-out of the normal ResolverActivity behavior.
+     *
+     * TODO: this should be removed later on in the unbundling migration, when the springboard
+     * activity no longer needs to derive from ResolverActivity. The hold-over design here is
+     * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
+     * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
+     * implementations that depend on the invariants that are violated in the headless mode). If
+     * necessary, we could instead consider using a springboard-only activity on the system side
+     * immediately, which would delegate either to the unbundled chooser, or to a
+     * (properly-inheriting) system ChooserActivity. This would have performance implications even
+     * when the unbundling experiment is disabled.
+     */
+    protected void super_onRestoreInstanceState(Bundle savedInstanceState) {
+        super.onRestoreInstanceState(savedInstanceState);
+    }
+
+    /**
+     * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
+     * where we hand over to the unbundled chooser (while violating many of the invariants of a
+     * typical ResolverActivity implementation). Subclasses running in this mode need to be able
+     * to opt-out of the normal ResolverActivity behavior.
+     *
+     * TODO: this should be removed later on in the unbundling migration, when the springboard
+     * activity no longer needs to derive from ResolverActivity. The hold-over design here is
+     * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
+     * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
+     * implementations that depend on the invariants that are violated in the headless mode). If
+     * necessary, we could instead consider using a springboard-only activity on the system side
+     * immediately, which would delegate either to the unbundled chooser, or to a
+     * (properly-inheriting) system ChooserActivity. This would have performance implications even
+     * when the unbundling experiment is disabled.
+     */
+    public void super_onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+    }
+
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         // Use a specialized prompt when we're handling the 'Home' app startActivity()
@@ -877,7 +957,7 @@
         }
         final Intent intent = getIntent();
         if ((intent.getFlags() & FLAG_ACTIVITY_NEW_TASK) != 0 && !isVoiceInteraction()
-                && !mResolvingHome && !mRetainInOnStop) {
+                && !mResolvingHome && !mRetainInOnStop && !mAwaitingDelegateResponse) {
             // This resolver is in the unusual situation where it has been
             // launched at the top of a new task.  We don't let it be added
             // to the recent tasks shown to the user, and we need to make sure
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index bff813e..6a6f60e 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -512,6 +512,11 @@
      */
     public static final String DEFAULT_QR_CODE_SCANNER = "default_qr_code_scanner";
 
+    /**
+     * (boolean) Whether the task manager entrypoint is enabled.
+     */
+    public static final String TASK_MANAGER_ENABLED = "task_manager_enabled";
+
     private SystemUiDeviceConfigFlags() {
     }
 }
diff --git a/core/java/com/android/internal/net/OWNERS b/core/java/com/android/internal/net/OWNERS
index 050cb5c..71f997b 100644
--- a/core/java/com/android/internal/net/OWNERS
+++ b/core/java/com/android/internal/net/OWNERS
@@ -1,9 +1,4 @@
 set noparent
+file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking
 
-codewiz@google.com
-ek@google.com
-jchalard@google.com
 jsharkey@android.com
-lorenzo@google.com
-reminv@google.com
-satk@google.com
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 9140bb8..3aac0b1 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -468,6 +468,7 @@
             mPendingUids.clear();
         }
         final long timestampMs = mClock.elapsedRealtime();
+        LongArrayMultiStateCounter.LongArrayContainer deltaContainer = null;
         for (int i = uidStates.size() - 1; i >= 0; --i) {
             final int uid = uidStates.keyAt(i);
             final int procState = uidStates.valueAt(i);
@@ -493,6 +494,9 @@
                         isolatedUids[j] = u.mChildUids.keyAt(j);
                         isolatedUidTimeInFreqCounters[j] =
                                 u.mChildUids.valueAt(j).cpuTimeInFreqCounter;
+                        if (deltaContainer == null && isolatedUidTimeInFreqCounters[j] != null) {
+                            deltaContainer = getCpuTimeInFreqContainer();
+                        }
                     }
                 }
             }
@@ -509,8 +513,6 @@
             mKernelSingleUidTimeReader.addDelta(uid, onBatteryScreenOffCounter, timestampMs);
 
             if (isolatedUids != null) {
-                LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
-                        new LongArrayMultiStateCounter.LongArrayContainer(getCpuFreqCount());
                 for (int j = isolatedUids.length - 1; j >= 0; --j) {
                     if (isolatedUidTimeInFreqCounters[j] != null) {
                         mKernelSingleUidTimeReader.addDelta(isolatedUids[j],
@@ -612,13 +614,13 @@
                 }
 
                 if (u.mChildUids != null) {
-                    final LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
-                            new LongArrayMultiStateCounter.LongArrayContainer(getCpuFreqCount());
                     for (int j = u.mChildUids.size() - 1; j >= 0; --j) {
                         final LongArrayMultiStateCounter counter =
                                 u.mChildUids.valueAt(j).cpuTimeInFreqCounter;
                         if (counter != null) {
                             final int isolatedUid = u.mChildUids.keyAt(j);
+                            final LongArrayMultiStateCounter.LongArrayContainer deltaContainer =
+                                    getCpuTimeInFreqContainer();
                             mKernelSingleUidTimeReader.addDelta(isolatedUid,
                                     counter, timestampMs, deltaContainer);
                             onBatteryCounter.addCounts(deltaContainer);
@@ -1186,7 +1188,9 @@
 
     private long mBatteryTimeToFullSeconds = -1;
 
+    private boolean mCpuFreqsInitialized;
     private long[] mCpuFreqs;
+    private LongArrayMultiStateCounter.LongArrayContainer mTmpCpuTimeInFreq;
 
     /**
      * Times spent by the system server threads handling incoming binder requests.
@@ -1931,23 +1935,22 @@
         }
 
         /**
-         * Returns accumulated counts for the specified state, or null if all counts are zero.
+         * Returns accumulated counts for the specified state, or false if all counts are zero.
          */
-        @Nullable
-        public long[] getCountsLocked(int which, int procState) {
-            LongArrayMultiStateCounter.LongArrayContainer longArrayContainer =
-                    new LongArrayMultiStateCounter.LongArrayContainer(mCounter.getArrayLength());
-            mCounter.getCounts(longArrayContainer, procState);
-            final long[] counts = new long[mCounter.getArrayLength()];
-            longArrayContainer.getValues(counts);
+        public boolean getCountsLocked(long[] counts, int procState) {
+            if (counts.length != mCounter.getArrayLength()) {
+                return false;
+            }
+
+            mCounter.getCounts(counts, procState);
 
             // Return counts only if at least one of the elements is non-zero.
             for (int i = counts.length - 1; i >= 0; --i) {
                 if (counts[i] != 0) {
-                    return counts;
+                    return true;
                 }
             }
-            return null;
+            return false;
         }
 
         public void logState(Printer pw, String prefix) {
@@ -3519,6 +3522,10 @@
      * <code>(index | TAG_FIRST_OCCURRENCE_FLAG)</code>
      */
     private int writeHistoryTag(HistoryTag tag) {
+        if (tag.string == null) {
+            Slog.wtfStack(TAG, "writeHistoryTag called with null name");
+        }
+
         Integer idxObj = mHistoryTagPool.get(tag);
         int idx;
         if (idxObj != null) {
@@ -8346,35 +8353,34 @@
 
         @GuardedBy("mBsi")
         @Override
-        public long[] getCpuFreqTimes(int which, int procState) {
+        public boolean getCpuFreqTimes(long[] timesInFreqMs, int procState) {
             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
-                return null;
+                return false;
             }
             if (mProcStateTimeMs == null) {
-                return null;
+                return false;
             }
             if (!mBsi.mPerProcStateCpuTimesAvailable) {
                 mProcStateTimeMs = null;
-                return null;
+                return false;
             }
-
-            return mProcStateTimeMs.getCountsLocked(which, procState);
+            return mProcStateTimeMs.getCountsLocked(timesInFreqMs, procState);
         }
 
         @GuardedBy("mBsi")
         @Override
-        public long[] getScreenOffCpuFreqTimes(int which, int procState) {
+        public boolean getScreenOffCpuFreqTimes(long[] timesInFreqMs, int procState) {
             if (procState < 0 || procState >= NUM_PROCESS_STATE) {
-                return null;
+                return false;
             }
             if (mProcStateScreenOffTimeMs == null) {
-                return null;
+                return false;
             }
             if (!mBsi.mPerProcStateCpuTimesAvailable) {
                 mProcStateScreenOffTimeMs = null;
-                return null;
+                return false;
             }
-            return mProcStateScreenOffTimeMs.getCountsLocked(which, procState);
+            return mProcStateScreenOffTimeMs.getCountsLocked(timesInFreqMs, procState);
         }
 
         public long getBinderCallCount() {
@@ -11577,18 +11583,30 @@
         }
     }
 
+    @GuardedBy("this")
+    @Override
     public long[] getCpuFreqs() {
+        if (!mCpuFreqsInitialized) {
+            mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
+            mCpuFreqsInitialized = true;
+        }
         return mCpuFreqs;
     }
 
-    /**
-     * Returns the total number of frequencies across all CPU clusters.
-     */
-    private int getCpuFreqCount() {
-        if (mCpuFreqs == null) {
-            mCpuFreqs = mCpuUidFreqTimeReader.readFreqs(mPowerProfile);
+    @GuardedBy("this")
+    @Override
+    public int getCpuFreqCount() {
+        final long[] cpuFreqs = getCpuFreqs();
+        return cpuFreqs != null ? cpuFreqs.length : 0;
+    }
+
+    @GuardedBy("this")
+    private LongArrayMultiStateCounter.LongArrayContainer getCpuTimeInFreqContainer() {
+        if (mTmpCpuTimeInFreq == null) {
+            mTmpCpuTimeInFreq =
+                    new LongArrayMultiStateCounter.LongArrayContainer(getCpuFreqCount());
         }
-        return mCpuFreqs != null ? mCpuFreqs.length : 0;
+        return mTmpCpuTimeInFreq;
     }
 
     public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb,
diff --git a/core/java/com/android/internal/os/ClassLoaderFactory.java b/core/java/com/android/internal/os/ClassLoaderFactory.java
index 8b0411d..8f5e97d 100644
--- a/core/java/com/android/internal/os/ClassLoaderFactory.java
+++ b/core/java/com/android/internal/os/ClassLoaderFactory.java
@@ -24,6 +24,7 @@
 import dalvik.system.DexClassLoader;
 import dalvik.system.PathClassLoader;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -100,14 +101,25 @@
     }
 
     /**
-     * Same as {@code createClassLoader} below, but passes a null list of shared
-     * libraries.
+     * Same as {@code createClassLoader} below, but passes a null list of shared libraries. This
+     * method is used only to load platform classes (i.e. those in framework.jar or services.jar),
+     * and MUST NOT be used for loading untrusted classes, especially the app classes. For the
+     * latter case, use the below method which accepts list of shared libraries so that the classes
+     * don't have unlimited access to all shared libraries.
      */
     public static ClassLoader createClassLoader(String dexPath,
             String librarySearchPath, String libraryPermittedPath, ClassLoader parent,
             int targetSdkVersion, boolean isNamespaceShared, String classLoaderName) {
+        // b/205164833: allow framework classes to have access to all public vendor libraries.
+        // This is because those classes are part of the platform and don't have an app manifest
+        // where required libraries can be specified using the <uses-native-library> tag.
+        // Note that this still does not give access to "private" vendor libraries.
+        List<String> nativeSharedLibraries = new ArrayList<>();
+        nativeSharedLibraries.add("ALL");
+
         return createClassLoader(dexPath, librarySearchPath, libraryPermittedPath,
-            parent, targetSdkVersion, isNamespaceShared, classLoaderName, null, null, null);
+            parent, targetSdkVersion, isNamespaceShared, classLoaderName, null,
+            nativeSharedLibraries, null);
     }
 
     /**
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index 4ab4fae..175f28f 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -56,6 +56,7 @@
         public long durationFgMs;
         public String packageWithHighestDrain;
         public double[] perProcStatePowerMah;
+        public long[] cpuFreqTimes;
     }
 
     public CpuPowerCalculator(PowerProfile profile) {
@@ -98,6 +99,9 @@
 
         BatteryConsumer.Key[] keys = UNINITIALIZED_KEYS;
         Result result = new Result();
+        if (query.isProcessStateDataNeeded()) {
+            result.cpuFreqTimes = new long[batteryStats.getCpuFreqCount()];
+        }
         final SparseArray<UidBatteryConsumer.Builder> uidBatteryConsumerBuilders =
                 builder.getUidBatteryConsumerBuilders();
         for (int i = uidBatteryConsumerBuilders.size() - 1; i >= 0; i--) {
@@ -187,11 +191,10 @@
             // TODO(b/191921016): use per-state CPU cluster times
             final long[] cpuClusterTimes = null;
 
-            final long[] cpuFreqTimes = u.getCpuFreqTimes(BatteryStats.STATS_SINCE_CHARGED,
-                    uidProcState);
-            if (cpuClusterTimes != null || cpuFreqTimes != null) {
+            boolean hasCpuFreqTimes = u.getCpuFreqTimes(result.cpuFreqTimes, uidProcState);
+            if (cpuClusterTimes != null || hasCpuFreqTimes) {
                 result.perProcStatePowerMah[procState] += calculateUidModeledPowerMah(u,
-                        0, cpuClusterTimes, cpuFreqTimes);
+                        0, cpuClusterTimes, result.cpuFreqTimes);
             }
         }
 
diff --git a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
index d98b73f..50dcca64 100644
--- a/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
+++ b/core/java/com/android/internal/os/LongArrayMultiStateCounter.java
@@ -27,6 +27,7 @@
 import libcore.util.NativeAllocationRegistry;
 
 import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicReference;
 
 /**
  * Performs per-state counting of multi-element values over time. The class' behavior is illustrated
@@ -120,6 +121,8 @@
     private static final NativeAllocationRegistry sRegistry =
             NativeAllocationRegistry.createMalloced(
                     LongArrayMultiStateCounter.class.getClassLoader(), native_getReleaseFunc());
+    private static final AtomicReference<LongArrayContainer> sTmpArrayContainer =
+            new AtomicReference<>();
 
     private final int mStateCount;
     private final int mLength;
@@ -204,6 +207,19 @@
     }
 
     /**
+     * Populates the array with the accumulated counts for the specified state.
+     */
+    public void getCounts(long[] counts, int state) {
+        LongArrayContainer container = sTmpArrayContainer.getAndSet(null);
+        if (container == null || container.mLength != counts.length) {
+            container = new LongArrayContainer(counts.length);
+        }
+        getCounts(container, state);
+        container.getValues(counts);
+        sTmpArrayContainer.set(container);
+    }
+
+    /**
      * Populates longArrayContainer with the accumulated counts for the specified state.
      */
     public void getCounts(LongArrayContainer longArrayContainer, int state) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 92d5a47..6d4b8c5 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -724,9 +724,6 @@
         DataOutputStream usapOutputStream = null;
         ZygoteArguments args = null;
 
-        // Block SIGTERM so we won't be killed if the Zygote flushes the USAP pool.
-        blockSigTerm();
-
         LocalSocket sessionSocket = null;
         if (argBuffer == null) {
             // Read arguments from usapPoolSocket instead.
@@ -742,6 +739,10 @@
                 ZygoteCommandBuffer tmpArgBuffer = null;
                 try {
                     sessionSocket = usapPoolSocket.accept();
+                    // Block SIGTERM so we won't be killed if the Zygote flushes the USAP pool.
+                    // This is safe from a race condition because the pool is only flushed after
+                    // the SystemServer changes its internal state to stop using the USAP pool.
+                    blockSigTerm();
 
                     usapOutputStream =
                             new DataOutputStream(sessionSocket.getOutputStream());
@@ -759,9 +760,10 @@
                 unblockSigTerm();
                 IoUtils.closeQuietly(sessionSocket);
                 IoUtils.closeQuietly(tmpArgBuffer);
-                blockSigTerm();
             }
         } else {
+            // Block SIGTERM so we won't be killed if the Zygote flushes the USAP pool.
+            blockSigTerm();
             try {
                 args = ZygoteArguments.getInstance(argBuffer);
             } catch (Exception ex) {
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index b428970..7755b69 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -1842,7 +1842,7 @@
     @Override
     public void setLocalFocus(boolean hasFocus, boolean inTouchMode) {
         ViewRootImpl viewRoot = getViewRootImpl();
-        viewRoot.windowFocusChanged(hasFocus, inTouchMode);
+        viewRoot.windowFocusChanged(hasFocus);
         viewRoot.touchModeChanged(inTouchMode);
     }
 
diff --git a/core/java/com/android/internal/protolog/ProtoLogGroup.java b/core/java/com/android/internal/protolog/ProtoLogGroup.java
index 954204f..5ac4936 100644
--- a/core/java/com/android/internal/protolog/ProtoLogGroup.java
+++ b/core/java/com/android/internal/protolog/ProtoLogGroup.java
@@ -84,7 +84,7 @@
             Consts.TAG_WM),
     WM_DEBUG_LAYER_MIRRORING(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true,
             Consts.TAG_WM),
-    WM_DEBUG_WALLPAPER(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true, Consts.TAG_WM),
+    WM_DEBUG_WALLPAPER(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM),
     TEST_GROUP(true, true, false, "WindowManagerProtoLogTest");
 
     private final boolean mEnabled;
diff --git a/core/java/com/android/internal/util/Parcelling.java b/core/java/com/android/internal/util/Parcelling.java
index 1ab316d..3147c34 100644
--- a/core/java/com/android/internal/util/Parcelling.java
+++ b/core/java/com/android/internal/util/Parcelling.java
@@ -23,6 +23,7 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
+import java.time.Instant;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -306,5 +307,33 @@
                 return string == null ? null : UUID.fromString(string);
             }
         }
+
+        /**
+         * A {@link Parcelling} for {@link Instant}.
+         *
+         * The minimum value of an instant uses a millisecond offset of about -3.15e19 which is
+         * larger than Long.MIN_VALUE, so we can use Long.MIN_VALUE as a sentinel value to indicate
+         * a null Instant.
+         */
+        class ForInstant implements Parcelling<Instant> {
+
+            @Override
+            public void parcel(Instant item, Parcel dest, int parcelFlags) {
+                dest.writeLong(item == null ? Long.MIN_VALUE : item.getEpochSecond());
+                dest.writeInt(item == null ? Integer.MIN_VALUE : item.getNano());
+            }
+
+            @Override
+            public Instant unparcel(Parcel source) {
+                long epochSecond = source.readLong();
+                int afterNano = source.readInt();
+
+                if (epochSecond == Long.MIN_VALUE) {
+                    return null;
+                } else {
+                    return Instant.ofEpochSecond(epochSecond, afterNano);
+                }
+            }
+        }
     }
 }
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 9e741e2..6673f67 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -90,10 +90,6 @@
     }
 
     @Override
-    public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
-    }
-
-    @Override
     public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
         if (out != null) {
             try {
diff --git a/core/java/com/android/internal/view/OWNERS b/core/java/com/android/internal/view/OWNERS
index eb2478f..7a590d0 100644
--- a/core/java/com/android/internal/view/OWNERS
+++ b/core/java/com/android/internal/view/OWNERS
@@ -15,7 +15,7 @@
 
 # WindowManager
 per-file AppearanceRegion = file:/services/core/java/com/android/server/wm/OWNERS
-per-file BaseIWIndow.java = file:/services/core/java/com/android/server/wm/OWNERS
+per-file BaseIWindow.java = file:/services/core/java/com/android/server/wm/OWNERS
 per-file RotationPolicy.java = file:/services/core/java/com/android/server/wm/OWNERS
 per-file WindowManagerPolicyThread.java = file:/services/core/java/com/android/server/wm/OWNERS
 
diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java
index 2959667..26ff192 100644
--- a/core/java/com/android/server/NetworkManagementSocketTagger.java
+++ b/core/java/com/android/server/NetworkManagementSocketTagger.java
@@ -17,7 +17,6 @@
 package com.android.server;
 
 import android.os.StrictMode;
-import android.os.SystemProperties;
 import android.util.Log;
 import android.util.Slog;
 
@@ -33,13 +32,6 @@
     private static final String TAG = "NetworkManagementSocketTagger";
     private static final boolean LOGD = false;
 
-    /**
-     * {@link SystemProperties} key that indicates if {@code qtaguid} bandwidth
-     * controls have been enabled.
-     */
-    // TODO: remove when always enabled, or once socket tagging silently fails.
-    public static final String PROP_QTAGUID_ENABLED = "net.qtaguid_enabled";
-
     private static ThreadLocal<SocketTags> threadSocketTags = new ThreadLocal<SocketTags>() {
         @Override
         protected SocketTags initialValue() {
@@ -88,13 +80,11 @@
     private void tagSocketFd(FileDescriptor fd, int tag, int uid) {
         if (tag == -1 && uid == -1) return;
 
-        if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
-            final int errno = native_tagSocketFd(fd, tag, uid);
-            if (errno < 0) {
-                Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
-                      + tag + ", " +
-                      + uid + ") failed with errno" + errno);
-            }
+        final int errno = native_tagSocketFd(fd, tag, uid);
+        if (errno < 0) {
+            Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
+                    + tag + ", "
+                    + uid + ") failed with errno" + errno);
         }
     }
 
@@ -110,11 +100,9 @@
         final SocketTags options = threadSocketTags.get();
         if (options.statsTag == -1 && options.statsUid == -1) return;
 
-        if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
-            final int errno = native_untagSocketFd(fd);
-            if (errno < 0) {
-                Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
-            }
+        final int errno = native_untagSocketFd(fd);
+        if (errno < 0) {
+            Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
         }
     }
 
@@ -124,21 +112,17 @@
     }
 
     public static void setKernelCounterSet(int uid, int counterSet) {
-        if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
-            final int errno = native_setCounterSet(counterSet, uid);
-            if (errno < 0) {
-                Log.w(TAG, "setKernelCountSet(" + uid + ", " + counterSet + ") failed with errno "
-                        + errno);
-            }
+        final int errno = native_setCounterSet(counterSet, uid);
+        if (errno < 0) {
+            Log.w(TAG, "setKernelCountSet(" + uid + ", " + counterSet + ") failed with errno "
+                    + errno);
         }
     }
 
     public static void resetKernelUidStats(int uid) {
-        if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
-            int errno = native_deleteTagData(0, uid);
-            if (errno < 0) {
-                Slog.w(TAG, "problem clearing counters for uid " + uid + " : errno " + errno);
-            }
+        int errno = native_deleteTagData(0, uid);
+        if (errno < 0) {
+            Slog.w(TAG, "problem clearing counters for uid " + uid + " : errno " + errno);
         }
     }
 
diff --git a/core/java/com/android/server/net/OWNERS b/core/java/com/android/server/net/OWNERS
index d3836d4..62c5737 100644
--- a/core/java/com/android/server/net/OWNERS
+++ b/core/java/com/android/server/net/OWNERS
@@ -1,8 +1,2 @@
 set noparent
-
-codewiz@google.com
-jchalard@google.com
-junyulai@google.com
-lorenzo@google.com
-reminv@google.com
-satk@google.com
+file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 5c9b6df..18e85b6 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -750,8 +750,9 @@
     }
 
     const bool checkJni = GetBoolProperty("dalvik.vm.checkjni", false);
-    ALOGV("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
     if (checkJni) {
+        ALOGD("CheckJNI is ON");
+
         /* extended JNI checking */
         addOption("-Xcheck:jni");
 
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 6cea8bf..f2bcb02 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -73,6 +73,9 @@
 # Although marked "view" this is mostly graphics stuff
 per-file android_view_* = file:/graphics/java/android/graphics/OWNERS
 
+# Verity
+per-file com_android_internal_security_Verity* = ebiggers@google.com, victorhsieh@google.com
+
 # VINTF
 per-file android_os_VintfObject* = file:platform/system/libvintf:/OWNERS
 per-file android_os_VintfRuntimeInfo* = file:platform/system/libvintf:/OWNERS
diff --git a/core/jni/android_graphics_BLASTBufferQueue.cpp b/core/jni/android_graphics_BLASTBufferQueue.cpp
index cdfd089..e7b3fba 100644
--- a/core/jni/android_graphics_BLASTBufferQueue.cpp
+++ b/core/jni/android_graphics_BLASTBufferQueue.cpp
@@ -79,7 +79,7 @@
                                            jlong framenumber) {
     sp<BLASTBufferQueue> queue = reinterpret_cast<BLASTBufferQueue*>(ptr);
     auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionPtr);
-    queue->mergeWithNextTransaction(transaction, framenumber);
+    queue->mergeWithNextTransaction(transaction, CC_UNLIKELY(framenumber < 0) ? 0 : framenumber);
 }
 
 static jlong nativeGetLastAcquiredFrameNum(JNIEnv* env, jclass clazz, jlong ptr) {
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 4c2b114..5e0d9b3 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -34,6 +34,7 @@
 #include <vector>
 
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <bionic/malloc.h>
 #include <debuggerd/client.h>
 #include <log/log.h>
@@ -859,7 +860,22 @@
     return poolsSizeKb;
 }
 
+static bool halSupportsGpuPrivateMemory() {
+    int productApiLevel =
+            android::base::GetIntProperty("ro.product.first_api_level",
+                                          android::base::GetIntProperty("ro.build.version.sdk",
+                                                                         __ANDROID_API_FUTURE__));
+    int boardApiLevel =
+            android::base::GetIntProperty("ro.board.api_level",
+                                          android::base::GetIntProperty("ro.board.first_api_level",
+                                                                         __ANDROID_API_FUTURE__));
+
+    return std::min(productApiLevel, boardApiLevel) >= __ANDROID_API_S__;
+}
+
 static jlong android_os_Debug_getGpuPrivateMemoryKb(JNIEnv* env, jobject clazz) {
+    static bool gpuPrivateMemorySupported = halSupportsGpuPrivateMemory();
+
     struct memtrack_proc* p = memtrack_proc_new();
     if (p == nullptr) {
         LOG(ERROR) << "getGpuPrivateMemoryKb: Failed to create memtrack_proc";
@@ -876,6 +892,12 @@
     ssize_t gpuPrivateMem = memtrack_proc_gl_pss(p);
 
     memtrack_proc_destroy(p);
+
+    // Old HAL implementations may return 0 for GPU private memory if not supported
+    if (gpuPrivateMem == 0 && !gpuPrivateMemorySupported) {
+        return -1;
+    }
+
     return gpuPrivateMem / 1024;
 }
 
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 4d8d4db..7c67cbc 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -1346,7 +1346,7 @@
         {"createProcessGroup", "(II)I", (void*)android_os_Process_createProcessGroup},
         {"getExclusiveCores", "()[I", (void*)android_os_Process_getExclusiveCores},
         {"setSwappiness", "(IZ)Z", (void*)android_os_Process_setSwappiness},
-        {"setArgV0", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
+        {"setArgV0Native", "(Ljava/lang/String;)V", (void*)android_os_Process_setArgV0},
         {"setUid", "(I)I", (void*)android_os_Process_setUid},
         {"setGid", "(I)I", (void*)android_os_Process_setGid},
         {"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
diff --git a/core/jni/android_view_CompositionSamplingListener.cpp b/core/jni/android_view_CompositionSamplingListener.cpp
index 783b0d4..59c01dc 100644
--- a/core/jni/android_view_CompositionSamplingListener.cpp
+++ b/core/jni/android_view_CompositionSamplingListener.cpp
@@ -16,21 +16,19 @@
 
 #define LOG_TAG "CompositionSamplingListener"
 
-#include "android_util_Binder.h"
-#include "core_jni_helpers.h"
-
-#include <nativehelper/JNIHelp.h>
-
+#include <android/gui/BnRegionSamplingListener.h>
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/Log.h>
-#include <utils/Log.h>
-#include <utils/RefBase.h>
 #include <binder/IServiceManager.h>
-
-#include <gui/IRegionSamplingListener.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/SurfaceComposerClient.h>
+#include <nativehelper/JNIHelp.h>
 #include <ui/Rect.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+
+#include "android_util_Binder.h"
+#include "core_jni_helpers.h"
 
 namespace android {
 
@@ -41,18 +39,18 @@
     jmethodID mDispatchOnSampleCollected;
 } gListenerClassInfo;
 
-struct CompositionSamplingListener : public BnRegionSamplingListener {
+struct CompositionSamplingListener : public gui::BnRegionSamplingListener {
     CompositionSamplingListener(JNIEnv* env, jobject listener)
             : mListener(env->NewWeakGlobalRef(listener)) {}
 
-    void onSampleCollected(float medianLuma) override {
+    binder::Status onSampleCollected(float medianLuma) override {
         JNIEnv* env = AndroidRuntime::getJNIEnv();
         LOG_ALWAYS_FATAL_IF(env == nullptr, "Unable to retrieve JNIEnv in onSampleCollected.");
 
         jobject listener = env->NewGlobalRef(mListener);
         if (listener == NULL) {
             // Weak reference went out of scope
-            return;
+            return binder::Status::ok();
         }
         env->CallStaticVoidMethod(gListenerClassInfo.mClass,
                 gListenerClassInfo.mDispatchOnSampleCollected, listener,
@@ -64,6 +62,8 @@
             LOGE_EX(env);
             env->ExceptionClear();
         }
+
+        return binder::Status::ok();
     }
 
 protected:
diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp
index 67ab30b..1159c8a 100644
--- a/core/jni/android_view_InputEventReceiver.cpp
+++ b/core/jni/android_view_InputEventReceiver.cpp
@@ -390,13 +390,11 @@
             case AINPUT_EVENT_TYPE_FOCUS: {
                 FocusEvent* focusEvent = static_cast<FocusEvent*>(inputEvent);
                 if (kDebugDispatchCycle) {
-                    ALOGD("channel '%s' ~ Received focus event: hasFocus=%s, inTouchMode=%s.",
-                          getInputChannelName().c_str(), toString(focusEvent->getHasFocus()),
-                          toString(focusEvent->getInTouchMode()));
+                    ALOGD("channel '%s' ~ Received focus event: hasFocus=%s.",
+                          getInputChannelName().c_str(), toString(focusEvent->getHasFocus()));
                 }
                 env->CallVoidMethod(receiverObj.get(), gInputEventReceiverClassInfo.onFocusEvent,
-                                    jboolean(focusEvent->getHasFocus()),
-                                    jboolean(focusEvent->getInTouchMode()));
+                                    jboolean(focusEvent->getHasFocus()));
                 finishInputEvent(seq, true /* handled */);
                 continue;
             }
@@ -615,7 +613,7 @@
             gInputEventReceiverClassInfo.clazz,
             "dispatchInputEvent", "(ILandroid/view/InputEvent;)V");
     gInputEventReceiverClassInfo.onFocusEvent =
-            GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onFocusEvent", "(ZZ)V");
+            GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onFocusEvent", "(Z)V");
     gInputEventReceiverClassInfo.onPointerCaptureEvent =
             GetMethodIDOrDie(env, gInputEventReceiverClassInfo.clazz, "onPointerCaptureEvent",
                              "(Z)V");
diff --git a/core/jni/com_android_internal_security_VerityUtils.cpp b/core/jni/com_android_internal_security_VerityUtils.cpp
index 411a392..c5b3d8a 100644
--- a/core/jni/com_android_internal_security_VerityUtils.cpp
+++ b/core/jni/com_android_internal_security_VerityUtils.cpp
@@ -16,25 +16,25 @@
 
 #define LOG_TAG "VerityUtils"
 
+#include <android-base/unique_fd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <linux/fsverity.h>
+#include <linux/stat.h>
 #include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedPrimitiveArray.h>
 #include <nativehelper/ScopedUtfChars.h>
-#include <utils/Log.h>
-#include "jni.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/fsverity.h>
-#include <linux/stat.h>
 #include <string.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
-
-#include <android-base/unique_fd.h>
+#include <utils/Log.h>
 
 #include <type_traits>
 
+#include "jni.h"
+
 namespace android {
 
 namespace {
@@ -73,18 +73,31 @@
 int statxForFsverity(JNIEnv *env, jobject /* clazz */, jstring filePath) {
     ScopedUtfChars path(env, filePath);
 
+    // Call statx and check STATX_ATTR_VERITY.
     struct statx out = {};
     if (statx(AT_FDCWD, path.c_str(), 0 /* flags */, STATX_ALL, &out) != 0) {
         return -errno;
     }
 
-    // Validity check.
-    if ((out.stx_attributes_mask & STATX_ATTR_VERITY) == 0) {
-        ALOGE("Unexpected, STATX_ATTR_VERITY not supported by kernel");
-        return -ENOSYS;
+    if (out.stx_attributes_mask & STATX_ATTR_VERITY) {
+        return (out.stx_attributes & STATX_ATTR_VERITY) != 0;
     }
 
-    return (out.stx_attributes & STATX_ATTR_VERITY) != 0;
+    // STATX_ATTR_VERITY is not supported for the file path.
+    // In this case, call ioctl(FS_IOC_GETFLAGS) and check FS_VERITY_FL.
+    ::android::base::unique_fd rfd(open(path.c_str(), O_RDONLY | O_CLOEXEC));
+    if (rfd.get() < 0) {
+        ALOGE("open failed at %s", path.c_str());
+        return -errno;
+    }
+
+    unsigned int flags;
+    if (ioctl(rfd.get(), FS_IOC_GETFLAGS, &flags) < 0) {
+        ALOGE("ioctl(FS_IOC_GETFLAGS) failed at %s", path.c_str());
+        return -errno;
+    }
+
+    return (flags & FS_VERITY_FL) != 0;
 }
 
 int measureFsverity(JNIEnv *env, jobject /* clazz */, jstring filePath, jbyteArray digest) {
diff --git a/core/proto/android/app/location_time_zone_manager.proto b/core/proto/android/app/location_time_zone_manager.proto
index 891e9fc..5fdcfdf 100644
--- a/core/proto/android/app/location_time_zone_manager.proto
+++ b/core/proto/android/app/location_time_zone_manager.proto
@@ -23,6 +23,19 @@
 option java_multiple_files = true;
 option java_outer_classname = "LocationTimeZoneManagerProto";
 
+// A state enum that matches states for LocationTimeZoneProviderController. See that class for
+// details.
+enum ControllerStateEnum {
+  CONTROLLER_STATE_UNKNOWN = 0;
+  CONTROLLER_STATE_PROVIDERS_INITIALIZING = 1;
+  CONTROLLER_STATE_STOPPED = 2;
+  CONTROLLER_STATE_INITIALIZING = 3;
+  CONTROLLER_STATE_UNCERTAIN = 4;
+  CONTROLLER_STATE_CERTAIN = 5;
+  CONTROLLER_STATE_FAILED = 6;
+  CONTROLLER_STATE_DESTROYED = 7;
+}
+
 // Represents the state of the LocationTimeZoneManagerService for use in tests.
 message LocationTimeZoneManagerServiceStateProto {
   option (android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -30,6 +43,7 @@
   optional GeolocationTimeZoneSuggestionProto last_suggestion = 1;
   repeated TimeZoneProviderStateProto primary_provider_states = 2;
   repeated TimeZoneProviderStateProto secondary_provider_states = 3;
+  repeated ControllerStateEnum controller_states = 4;
 }
 
 // The state tracked for a LocationTimeZoneProvider.
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index 83e26f6..db5d49d 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -601,7 +601,7 @@
     // ringer mode.
     optional SettingProto mode_ringer = 75 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
-    optional SettingProto apply_ramping_ringer = 147 [ (android.privacy).dest = DEST_AUTOMATIC ];
+    reserved 147; // Used to be apply_ramping_ringer
 
     message MultiSim {
         option (android.msg_privacy).dest = DEST_EXPLICIT;
diff --git a/core/proto/android/providers/settings/system.proto b/core/proto/android/providers/settings/system.proto
index f8b5b233..73d6a17 100644
--- a/core/proto/android/providers/settings/system.proto
+++ b/core/proto/android/providers/settings/system.proto
@@ -242,7 +242,9 @@
 
     optional SettingProto when_to_make_wifi_calls = 34 [ (android.privacy).dest = DEST_AUTOMATIC ];
 
+    optional SettingProto apply_ramping_ringer = 35 [ (android.privacy).dest = DEST_AUTOMATIC ];
+
     // Please insert fields in alphabetical order and group them into messages
     // if possible (to avoid reaching the method limit).
-    // Next tag = 35;
+    // Next tag = 36;
 }
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 8ef3825..211f78e 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -112,8 +112,9 @@
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
     optional bool keyguard_showing = 1;
-    repeated KeyguardOccludedProto keyguard_occluded_states = 2;
+    repeated KeyguardOccludedProto keyguard_occluded_states = 2 [deprecated=true];
     optional bool aod_showing = 3;
+    repeated KeyguardPerDisplayProto keyguard_per_display = 4;
 }
 
 message KeyguardOccludedProto {
@@ -123,6 +124,15 @@
     optional bool keyguard_occluded = 2;
 }
 
+message KeyguardPerDisplayProto {
+    option (.android.msg_privacy).dest = DEST_AUTOMATIC;
+
+    optional int32 display_id = 1;
+    optional bool keyguard_showing = 2;
+    optional bool aod_showing = 3;
+    optional bool keyguard_occluded = 4;
+}
+
 /* represents PhoneWindowManager */
 message WindowManagerPolicyProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5781b1e..85ae7a1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1751,6 +1751,13 @@
     <permission android:name="android.permission.ACCESS_MOCK_LOCATION"
         android:protectionLevel="signature" />
 
+    <!-- @SystemApi @hide Allows automotive applications to control location
+         suspend state for power management use cases.
+         <p>Not for use by third-party applications.
+    -->
+    <permission android:name="android.permission.AUTOMOTIVE_GNSS_CONTROLS"
+        android:protectionLevel="signature|privileged" />
+
     <!-- ======================================= -->
     <!-- Permissions for accessing networks -->
     <!-- ======================================= -->
@@ -1833,11 +1840,11 @@
     <permission android:name="android.permission.OVERRIDE_WIFI_CONFIG"
         android:protectionLevel="signature|privileged" />
 
-    <!-- Allows applications to act as network scorers. @hide @SystemApi-->
+    <!-- @deprecated Allows applications to act as network scorers. @hide @SystemApi-->
     <permission android:name="android.permission.SCORE_NETWORKS"
         android:protectionLevel="signature|privileged" />
 
-    <!-- Allows applications to request network
+    <!-- @deprecated Allows applications to request network
          recommendations and scores from the NetworkScoreService.
          @SystemApi
          <p>Not for use by third-party applications. @hide -->
@@ -3008,6 +3015,13 @@
     <permission android:name="android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION"
                 android:protectionLevel="internal|role" />
 
+    <!-- Allows an application to create a "self-managed" association.
+         @hide
+         @SystemApi
+    -->
+    <permission android:name="android.permission.REQUEST_COMPANION_SELF_MANAGED"
+                android:protectionLevel="signature|privileged" />
+
     <!-- Allows a companion app to associate to Wi-Fi.
          <p>Only for use by a single pre-approved app.
          @hide
@@ -3456,6 +3470,23 @@
     <permission android:name="android.permission.UPDATE_FONTS"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an application to use the AttestationVerificationService.
+         @hide -->
+    <permission android:name="android.permission.USE_ATTESTATION_VERIFICATION_SERVICE"
+                android:protectionLevel="signature" />
+
+    <!-- Allows an application to export a AttestationVerificationService to verify attestations on
+         behalf of AttestationVerificationManager for system-defined attestation profiles.
+         @hide -->
+    <permission android:name="android.permission.VERIFY_ATTESTATION"
+                android:protectionLevel="signature" />
+
+    <!-- Must be required by any AttestationVerificationService to ensure that only the system can
+         bind to it.
+         @hide -->
+    <permission android:name="android.permission.BIND_ATTESTATION_VERIFICATION_SERVICE"
+                android:protectionLevel="signature" />
+
     <!-- ========================================= -->
     <!-- Permissions for special development tools -->
     <!-- ========================================= -->
@@ -5956,6 +5987,14 @@
     <permission android:name="android.permission.CREATE_VIRTUAL_DEVICE"
                 android:protectionLevel="internal|role" />
 
+    <!-- @SystemApi Must be required by a safety source to send an update using the
+             {@link android.safetycenter.SafetyCenterManager}.
+             <p>Protection level: signature|privileged
+             @hide
+        -->
+    <permission android:name="android.permission.SEND_SAFETY_CENTER_UPDATE"
+                android:protectionLevel="signature|privileged" />
+
     <!-- Attribution for Geofencing service. -->
     <attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
     <!-- Attribution for Country Detector. -->
@@ -6388,6 +6427,10 @@
                  android:permission="android.permission.BIND_JOB_SERVICE">
         </service>
 
+        <service android:name="com.android.server.compos.IsolatedCompilationJobService"
+                 android:permission="android.permission.BIND_JOB_SERVICE">
+        </service>
+
         <service android:name="com.android.server.PruneInstantAppsJobService"
                  android:permission="android.permission.BIND_JOB_SERVICE" >
         </service>
diff --git a/core/res/res/anim/task_fragment_close_enter.xml b/core/res/res/anim/task_fragment_close_enter.xml
new file mode 100644
index 0000000..c940552
--- /dev/null
+++ b/core/res/res/anim/task_fragment_close_enter.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2021 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.
+   -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shareInterpolator="false">
+    <scale
+        android:fromXScale="1.1"
+        android:toXScale="1"
+        android:fromYScale="1.1"
+        android:toYScale="1"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_extra_slow_in"
+        android:duration="400"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/anim/task_fragment_close_exit.xml b/core/res/res/anim/task_fragment_close_exit.xml
new file mode 100644
index 0000000..8998f76
--- /dev/null
+++ b/core/res/res/anim/task_fragment_close_exit.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2021 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.
+   -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shareInterpolator="false"
+    android:zAdjustment="top">
+    <alpha
+        android:fromAlpha="1"
+        android:toAlpha="0.0"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/linear"
+        android:startOffset="33"
+        android:duration="50"/>
+    <scale
+        android:fromXScale="1"
+        android:toXScale="0.9"
+        android:fromYScale="1"
+        android:toYScale="0.9"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_extra_slow_in"
+        android:duration="400"/>
+</set>
diff --git a/core/res/res/anim/task_fragment_open_enter.xml b/core/res/res/anim/task_fragment_open_enter.xml
new file mode 100644
index 0000000..6bc47de
--- /dev/null
+++ b/core/res/res/anim/task_fragment_open_enter.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2021 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.
+   -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shareInterpolator="false">
+    <alpha
+        android:fromAlpha="0"
+        android:toAlpha="1.0"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/linear"
+        android:startOffset="50"
+        android:duration="50"/>
+    <scale
+        android:fromXScale="0.85"
+        android:toXScale="1"
+        android:fromYScale="0.85"
+        android:toYScale="1"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_extra_slow_in"
+        android:duration="400"/>
+</set>
diff --git a/core/res/res/anim/task_fragment_open_exit.xml b/core/res/res/anim/task_fragment_open_exit.xml
new file mode 100644
index 0000000..160eb84
--- /dev/null
+++ b/core/res/res/anim/task_fragment_open_exit.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright (C) 2021 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.
+   -->
+
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shareInterpolator="false">
+    <scale
+        android:fromXScale="1"
+        android:toXScale="1.05"
+        android:fromYScale="1"
+        android:toYScale="1.05"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillEnabled="true"
+        android:fillBefore="true"
+        android:fillAfter="true"
+        android:interpolator="@interpolator/fast_out_extra_slow_in"
+        android:duration="400"/>
+</set>
\ No newline at end of file
diff --git a/core/res/res/drawable-watch/global_actions_item_red_background_shape.xml b/core/res/res/drawable-watch/global_actions_item_red_background_shape.xml
index b556a1b..4f23700 100644
--- a/core/res/res/drawable-watch/global_actions_item_red_background_shape.xml
+++ b/core/res/res/drawable-watch/global_actions_item_red_background_shape.xml
@@ -18,5 +18,5 @@
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
     <corners android:radius="26dp"/>
-    <solid android:color="@color/wear_material_red_400"/>
+    <solid android:color="@color/wear_material_red_mid"/>
 </shape>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_qs_one_handed_mode.xml b/core/res/res/drawable/ic_qs_one_handed_mode.xml
new file mode 100644
index 0000000..18e5618
--- /dev/null
+++ b/core/res/res/drawable/ic_qs_one_handed_mode.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+   Copyright (C) 2021 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="18dp"
+        android:height="18dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
+
+    <path android:fillColor="@android:color/white"
+          android:pathData="M4.64169 3C3.88567 3 3.27271 3.61296 3.27271 4.36898V18.4011C3.27271 19.154 3.88875 19.7701 4.64169 19.7701H12.5339C12.5339 19.7701 12.5425 18.0588 11.2324 18.0588H6.01067C5.44597 18.0588 4.98393 17.5968 4.98393 17.0321V5.73797C4.98393 5.17326 5.44597 4.71123 6.01067 4.71123H15.9358C16.5005 4.71123 16.9625 5.17326 16.9625 5.73797V9.84492C16.9625 10.9651 16.4899 12.5952 15.5936 13.2674L9.77538 9.16043C8.58505 10.425 8.88177 11.705 10.1176 12.9251L13.1978 16.0053C13.1978 16.0053 13.3231 17.4572 13.5401 18.0588C14.2034 19.8984 16.2781 20.7968 16.2781 20.7968H19.231H19.2967C20.0835 20.7968 20.7273 20.153 20.7273 19.3662V12.2543L18.9441 4.06781C18.7662 3.23718 18.4068 3 17.8729 3H4.64169Z"/>
+</vector>
\ No newline at end of file
diff --git a/core/res/res/layout-watch/alert_dialog_material.xml b/core/res/res/layout-watch/alert_dialog_material.xml
index 960b927..1d56845 100644
--- a/core/res/res/layout-watch/alert_dialog_material.xml
+++ b/core/res/res/layout-watch/alert_dialog_material.xml
@@ -51,7 +51,7 @@
                         android:layout_width="match_parent"
                         android:layout_height="wrap_content"
                         android:gravity="center_horizontal|top"
-                        android:textAppearance="@style/TextAppearance.Material.Subhead"
+                        android:textAppearance="@style/TextAppearance.DeviceDefault.Body1"
                         android:paddingStart="?dialogPreferredPadding"
                         android:paddingEnd="?dialogPreferredPadding"
                         android:paddingTop="8dip"
diff --git a/core/res/res/layout-watch/preference_list_fragment_material.xml b/core/res/res/layout-watch/preference_list_fragment_material.xml
index 22e66d5..8f2658b 100644
--- a/core/res/res/layout-watch/preference_list_fragment_material.xml
+++ b/core/res/res/layout-watch/preference_list_fragment_material.xml
@@ -43,7 +43,7 @@
                 android:paddingStart="@dimen/dialog_padding_material"
                 android:paddingEnd="@dimen/dialog_padding_material"
                 android:paddingBottom="8dp"
-                android:textAppearance="@style/TextAppearance.Material.Title"
+                android:textAppearance="?android:attr/textAppearanceLarge"
                 android:gravity="center_horizontal|top" />
         </com.android.internal.widget.WatchHeaderListView>
     </FrameLayout>
diff --git a/core/res/res/layout-watch/progress_dialog_material.xml b/core/res/res/layout-watch/progress_dialog_material.xml
index 96bda1d..a7df948 100644
--- a/core/res/res/layout-watch/progress_dialog_material.xml
+++ b/core/res/res/layout-watch/progress_dialog_material.xml
@@ -40,7 +40,7 @@
 
         <TextView
             android:id="@+id/message"
-            android:textAppearance="?attr/textAppearanceListItem"
+            android:textAppearance="@style/TextAppearance.DeviceDefault.Subhead"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical" />
diff --git a/core/res/res/layout/splash_screen_view.xml b/core/res/res/layout/splash_screen_view.xml
index 2b9f952..304affe 100644
--- a/core/res/res/layout/splash_screen_view.xml
+++ b/core/res/res/layout/splash_screen_view.xml
@@ -36,6 +36,7 @@
           android:layout_marginBottom="60dp"
           android:padding="0dp"
           android:background="@null"
+          android:forceHasOverlappingRendering="false"
           android:contentDescription="@string/splash_screen_view_branding_description"/>
 
 </android.window.SplashScreenView>
\ No newline at end of file
diff --git a/core/res/res/mipmap-watch-anydpi/sym_def_app_icon_foreground.xml b/core/res/res/mipmap-watch-anydpi/sym_def_app_icon_foreground.xml
index 69c241c..68ccb3d 100644
--- a/core/res/res/mipmap-watch-anydpi/sym_def_app_icon_foreground.xml
+++ b/core/res/res/mipmap-watch-anydpi/sym_def_app_icon_foreground.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
 <inset
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:insetLeft="24dp"
-    android:insetRight="24dp"
-    android:insetTop="24dp"
-    android:insetBottom="24dp">
+    android:insetLeft="22.22%"
+    android:insetRight="22.22%"
+    android:insetTop="22.22%"
+    android:insetBottom="22.22%">
     <vector
         android:width="60dp"
         android:height="60dp"
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 363f833e..863912d 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1099,12 +1099,12 @@
     <string name="years" msgid="5797714729103773425">"أعوام"</string>
     <string name="now_string_shortest" msgid="3684914126941650330">"الآن"</string>
     <plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135">
-      <item quantity="zero"><xliff:g id="COUNT_1">%d</xliff:g>دقيقة</item>
-      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g> دقيقة</item>
+      <item quantity="zero"><xliff:g id="COUNT_1">%d</xliff:g> دقيقة</item>
+      <item quantity="two"><xliff:g id="COUNT_1">%d</xliff:g>  دقيقة</item>
       <item quantity="few"><xliff:g id="COUNT_1">%d</xliff:g> دقائق</item>
-      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g>دقيقة</item>
+      <item quantity="many"><xliff:g id="COUNT_1">%d</xliff:g> دقيقة</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> دقيقة</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g>دقيقة</item>
+      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> دقيقة</item>
     </plurals>
     <plurals name="duration_hours_shortest" formatted="false" msgid="2838655994500499651">
       <item quantity="zero"><xliff:g id="COUNT_1">%d</xliff:g> ساعة</item>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index f023d88..818166b 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -176,10 +176,10 @@
     <string name="contentServiceSync" msgid="2341041749565687871">"ছিংক ত্ৰুটি"</string>
     <string name="contentServiceSyncNotificationTitle" msgid="5766411446676388623">"ছিংক কৰিব নোৱাৰি"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="4562226280528716090">"একেলগে বহুত <xliff:g id="CONTENT_TYPE">%s</xliff:g> মচিবলৈ চেষ্টা কৰা হৈছে"</string>
-    <string name="low_memory" product="tablet" msgid="5557552311566179924">"টেবলেটৰ সঞ্চয়াগাৰত খালী ঠাই নাই। ঠাই খালী কৰিবলৈ কিছুমান ফাইল মচক।"</string>
-    <string name="low_memory" product="watch" msgid="3479447988234030194">"ঘড়ীৰ সঞ্চয়াগাৰ ভৰি পৰিছে। খালী স্থান উলিয়াবলৈ কিছুমান ফাইল মচক।"</string>
+    <string name="low_memory" product="tablet" msgid="5557552311566179924">"টেবলেটৰ ষ্ট’ৰেজত খালী ঠাই নাই। ঠাই খালী কৰিবলৈ কিছুমান ফাইল মচক।"</string>
+    <string name="low_memory" product="watch" msgid="3479447988234030194">"ঘড়ীৰ ষ্ট’ৰেজ ভৰি পৰিছে। খালী স্থান উলিয়াবলৈ কিছুমান ফাইল মচক।"</string>
     <string name="low_memory" product="tv" msgid="6663680413790323318">"Android TV ডিভাইচৰ ষ্ট’ৰেজ ভৰি পৰিছে। খালী ঠাই উলিয়াবলৈ কিছুমান ফাইল মচক।"</string>
-    <string name="low_memory" product="default" msgid="2539532364144025569">"ফ\'নৰ সঞ্চয়াগাৰত খালী ঠাই নাই। ঠাই খালী কৰিবলৈ কিছুমান ফাইল মচক।"</string>
+    <string name="low_memory" product="default" msgid="2539532364144025569">"ফ\'নৰ ষ্ট’ৰেজত খালী ঠাই নাই। ঠাই খালী কৰিবলৈ কিছুমান ফাইল মচক।"</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
       <item quantity="one">প্ৰমাণপত্ৰ প্ৰদানকাৰী কৰ্তৃপক্ষ ইনষ্টল কৰা হ’ল</item>
       <item quantity="other">প্ৰমাণপত্ৰ প্ৰদানকাৰী কৰ্তৃপক্ষ ইনষ্টল কৰা হ’ল</item>
@@ -400,7 +400,7 @@
     <string name="permdesc_persistentActivity" product="default" msgid="1914841924366562051">"মেম\'ৰিত নিজৰ বাবে প্ৰয়োজনীয় ঠাই পৃথক কৰিবলৈ এপক অনুমতি দিয়ে। এই কার্যই ফ\'নৰ কার্যক লেহেমীয়া কৰি অন্য এপবোৰৰ বাবে উপলব্ধ মেম\'ৰিক সীমাবদ্ধ কৰে।"</string>
     <string name="permlab_foregroundService" msgid="1768855976818467491">"অগ্ৰভূমিৰ সেৱা চলাব পাৰে"</string>
     <string name="permdesc_foregroundService" msgid="8720071450020922795">"এপটোক অগ্ৰভূমি সেৱাসমূহ ব্যৱহাৰ কৰিবলৈ অনুমতি দিয়ে।"</string>
-    <string name="permlab_getPackageSize" msgid="375391550792886641">"এপৰ সঞ্চয়াগাৰৰ খালী ঠাই হিচাপ কৰক"</string>
+    <string name="permlab_getPackageSize" msgid="375391550792886641">"এপৰ ষ্ট’ৰেজৰ খালী ঠাই হিচাপ কৰক"</string>
     <string name="permdesc_getPackageSize" msgid="742743530909966782">"এপটোক ইয়াৰ ক\'ড, ডেটা আৰু কেশ্বৰ আকাৰ বিচাৰি উলিয়াবলৈ অনুমতি দিয়ে"</string>
     <string name="permlab_writeSettings" msgid="8057285063719277394">"ছিষ্টেম ছেটিংহ সংশোধন কৰক"</string>
     <string name="permdesc_writeSettings" msgid="8293047411196067188">"এপ্‌টোক ছিষ্টেমৰ ছেটিঙৰ ডেটা সংশোধন কৰিবলৈ অনুমতি দিয়ে৷ ক্ষতিকাৰক এপ্‌সমূহে আপোনাৰ ছিষ্টেম কনফিগাৰেশ্বনক ক্ষতিগ্ৰস্ত কৰিব পাৰে৷"</string>
@@ -676,10 +676,10 @@
     <string name="permdesc_writeSyncSettings" msgid="6029151549667182687">"এপটোক কোনো একাউণ্টৰ ছিংক সম্পৰ্কীয় ছেটিংসমূহ সংশোধন কৰিবলৈ অনুমতি দিয়ে৷ উদাহৰণস্বৰূপে, এই কাৰ্যক কোনো একাউণ্টৰ জৰিয়তে People এপটোৰ ছিংক সক্ষম কৰিবলৈ ব্যৱহাৰ কৰিব পাৰি৷"</string>
     <string name="permlab_readSyncStats" msgid="3747407238320105332">"ছিংকৰ পৰিসংখ্যা পঢ়ক"</string>
     <string name="permdesc_readSyncStats" msgid="3867809926567379434">"ছিংকৰ কাৰ্যক্ৰমসমূহৰ ইতিহাস আৰু ছিংক কৰা ডেটাৰ পৰিমাণসহ কোনো একাউণ্টৰ ছিংকৰ তথ্য পঢ়িবলৈ এপক অনুমতি দিয়ে।"</string>
-    <string name="permlab_sdcardRead" msgid="5791467020950064920">"আপোনাৰ শ্বেয়াৰ কৰি ৰখা সঞ্চয়াগাৰৰ সমল পঢ়িব পাৰে"</string>
-    <string name="permdesc_sdcardRead" msgid="6872973242228240382">"আপোনাৰ শ্বেয়াৰ কৰি ৰখা সঞ্চয়াগাৰৰ সমল পঢ়িবলৈ এপটোক অনুমতি দিয়ে।"</string>
-    <string name="permlab_sdcardWrite" msgid="4863021819671416668">"আপোনাৰ শ্বেয়াৰ কৰি ৰখা সঞ্চয়াগাৰৰ সমল সংশোধন কৰিব বা মচিব পাৰে"</string>
-    <string name="permdesc_sdcardWrite" msgid="8376047679331387102">"আপোনাৰ শ্বেয়াৰ কৰি ৰখা সঞ্চয়াগাৰৰ সমল লিখিবলৈ এপটোক অনুমতি দিয়ে।"</string>
+    <string name="permlab_sdcardRead" msgid="5791467020950064920">"আপোনাৰ শ্বেয়াৰ কৰি ৰখা ষ্ট’ৰেজৰ সমল পঢ়িব পাৰে"</string>
+    <string name="permdesc_sdcardRead" msgid="6872973242228240382">"আপোনাৰ শ্বেয়াৰ কৰি ৰখা ষ্ট’ৰেজৰ সমল পঢ়িবলৈ এপ্‌টোক অনুমতি দিয়ে।"</string>
+    <string name="permlab_sdcardWrite" msgid="4863021819671416668">"আপোনাৰ শ্বেয়াৰ কৰি ৰখা ষ্ট’ৰেজৰ সমল সংশোধন কৰিব বা মচিব পাৰে"</string>
+    <string name="permdesc_sdcardWrite" msgid="8376047679331387102">"আপোনাৰ শ্বেয়াৰ কৰি ৰখা ষ্ট’ৰেজৰ সমল লিখিবলৈ এপ্‌টোক অনুমতি দিয়ে।"</string>
     <string name="permlab_use_sip" msgid="8250774565189337477">"SIP কল কৰা/পোৱা"</string>
     <string name="permdesc_use_sip" msgid="3590270893253204451">"এপটোক SIP কলসমূহ কৰিবলৈ আৰু পাবলৈ অনুমতি দিয়ে।"</string>
     <string name="permlab_register_sim_subscription" msgid="1653054249287576161">"নতুন টেলিকম ছিম সংযোগসমূহ পঞ্জীয়ন কৰা"</string>
@@ -757,7 +757,7 @@
     <string name="policydesc_setGlobalProxy" msgid="7149665222705519604">"নীতি সক্ষম কৰি থোৱা অৱস্থাত ব্য়ৱহাৰ কৰিবৰ বাবে ডিভাইচৰ বাবে গ্ল\'বেল প্ৰক্সী ছেট কৰক। কেৱল ডিভাইচৰ গৰাকীয়েহে গ্ল\'বেল প্ৰক্সী ছেট কৰিব পাৰে।"</string>
     <string name="policylab_expirePassword" msgid="6015404400532459169">"স্ক্ৰীন লক পাছৱৰ্ডৰ ম্যাদ ওকলাৰ দিন ছেট কৰক"</string>
     <string name="policydesc_expirePassword" msgid="9136524319325960675">"স্ক্ৰীন লকৰ পাছৱৰ্ড, পিন বা আর্হি কিমান ঘনাই সলনি কৰিব লাগিব তাক সলনি কৰক।"</string>
-    <string name="policylab_encryptedStorage" msgid="9012936958126670110">"সঞ্চয়াগাৰৰ এনক্ৰিপশ্বন ছেট কৰক"</string>
+    <string name="policylab_encryptedStorage" msgid="9012936958126670110">"ষ্ট’ৰেজৰ এনক্ৰিপশ্বন ছেট কৰক"</string>
     <string name="policydesc_encryptedStorage" msgid="1102516950740375617">"সঞ্চয় কৰি ৰখা ডেটাক এনক্ৰিপ্ট কৰাৰ প্ৰয়োজন।"</string>
     <string name="policylab_disableCamera" msgid="5749486347810162018">"কেমেৰাবোৰ অক্ষম কৰক"</string>
     <string name="policydesc_disableCamera" msgid="3204405908799676104">"আটাইবোৰ ডিভাইচৰ কেমেৰা ব্যৱহাৰ কৰাত বাধা দিয়ক।"</string>
@@ -1175,9 +1175,9 @@
     <string name="deleteText" msgid="4200807474529938112">"মচক"</string>
     <string name="inputMethod" msgid="1784759500516314751">"ইনপুট পদ্ধতি"</string>
     <string name="editTextMenuTitle" msgid="857666911134482176">"পাঠ বিষয়ক কাৰ্য"</string>
-    <string name="low_internal_storage_view_title" msgid="9024241779284783414">"সঞ্চয়াগাৰৰ খালী ঠাই শেষ হৈ আছে"</string>
+    <string name="low_internal_storage_view_title" msgid="9024241779284783414">"ষ্ট’ৰেজৰ খালী ঠাই শেষ হৈ আছে"</string>
     <string name="low_internal_storage_view_text" msgid="8172166728369697835">"ছিষ্টেমৰ কিছুমান কাৰ্যকলাপে কাম নকৰিবও পাৰে"</string>
-    <string name="low_internal_storage_view_text_no_boot" msgid="7368968163411251788">"ছিষ্টেমৰ বাবে পৰ্যাপ্ত খালী ঠাই নাই। আপোনাৰ ২৫০এম. বি. খালী ঠাই থকাটো নিশ্চিত কৰক আৰু ৰিষ্টাৰ্ট কৰক।"</string>
+    <string name="low_internal_storage_view_text_no_boot" msgid="7368968163411251788">"ছিষ্টেমৰ বাবে পৰ্যাপ্ত খালী ঠাই নাই। আপোনাৰ ২৫০এমবি খালী ঠাই থকাটো নিশ্চিত কৰক আৰু ৰিষ্টাৰ্ট কৰক।"</string>
     <string name="app_running_notification_title" msgid="8985999749231486569">"<xliff:g id="APP_NAME">%1$s</xliff:g> চলি আছে"</string>
     <string name="app_running_notification_text" msgid="5120815883400228566">"অধিক তথ্য জানিবলৈ বা এপ বন্ধ কৰিবলৈ টিপক।"</string>
     <string name="ok" msgid="2646370155170753815">"ঠিক আছে"</string>
@@ -1264,7 +1264,7 @@
     <string name="android_start_title" product="automotive" msgid="7917984412828168079">"Android আৰম্ভ কৰি থকা হৈছে…"</string>
     <string name="android_start_title" product="tablet" msgid="4429767260263190344">"টেবলেটটো আৰম্ভ হৈছে…"</string>
     <string name="android_start_title" product="device" msgid="6967413819673299309">"ডিভাইচটো আৰম্ভ হৈছে…"</string>
-    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"সঞ্চয়াগাৰ অপ্টিমাইজ কৰি থকা হৈছে।"</string>
+    <string name="android_upgrading_fstrim" msgid="3259087575528515329">"ষ্ট’ৰেজ অপ্টিমাইজ কৰি থকা হৈছে।"</string>
     <string name="android_upgrading_notification_title" product="default" msgid="3509927005342279257">"ছিষ্টেম আপডে’ট সম্পূৰ্ণ কৰা হৈছে…"</string>
     <string name="app_upgrading_toast" msgid="1016267296049455585">"<xliff:g id="APPLICATION">%1$s</xliff:g>ক আপগ্ৰেড কৰি থকা হৈছে…"</string>
     <string name="android_upgrading_apk" msgid="1339564803894466737">"<xliff:g id="NUMBER_1">%2$d</xliff:g>ৰ ভিতৰত <xliff:g id="NUMBER_0">%1$d</xliff:g> এপ্ অপ্টিমাইজ কৰি থকা হৈছে৷"</string>
@@ -1370,7 +1370,7 @@
     <string name="no_permissions" msgid="5729199278862516390">"কোনো অনুমতিৰ প্ৰয়োজন নাই"</string>
     <string name="perm_costs_money" msgid="749054595022779685">"ইয়াৰ ফলত আপোনাৰ টকা খৰচ হ\'ব পাৰে"</string>
     <string name="dlg_ok" msgid="5103447663504839312">"ঠিক আছে"</string>
-    <string name="usb_charging_notification_title" msgid="1674124518282666955">"ইউএছবিৰ জৰিয়তে এই ডিভাইচটো চ্চাৰ্জ কৰি থকা হৈছে"</string>
+    <string name="usb_charging_notification_title" msgid="1674124518282666955">"ইউএছবিৰ জৰিয়তে এই ডিভাইচটো চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="usb_supplying_notification_title" msgid="5378546632408101811">"ইউএছবিৰ জৰিয়তে সংযুক্ত ডিভাইচটো চ্চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="usb_mtp_notification_title" msgid="1065989144124499810">"ইউএছবি জৰিয়তে ফাইল স্থানান্তৰণ অন কৰা হ’ল"</string>
     <string name="usb_ptp_notification_title" msgid="5043437571863443281">"ইউএছবিৰ জৰিয়তে পিটিপি অন কৰা হ’ল"</string>
@@ -1436,7 +1436,7 @@
     <string name="ext_media_badremoval_notification_title" msgid="4114625551266196872">"<xliff:g id="NAME">%s</xliff:g> অপ্ৰত্য়াশিতভাৱে আঁতৰোৱা হ’ল"</string>
     <string name="ext_media_badremoval_notification_message" msgid="1986514704499809244">"সমল হেৰুওৱাৰ পৰা হাত সাৰিবলৈ আঁতৰোৱাৰ আগতে মিডিয়া বাহিৰ কৰক"</string>
     <string name="ext_media_nomedia_notification_title" msgid="742671636376975890">"<xliff:g id="NAME">%s</xliff:g> আঁতৰোৱা হ’ল"</string>
-    <string name="ext_media_nomedia_notification_message" msgid="2832724384636625852">"কিছুমান কাৰ্যক্ষমতাই সঠিকভাৱে কাম নকৰিব পাৰে। নতুন সঞ্চয়াগাৰ ভৰাওক।"</string>
+    <string name="ext_media_nomedia_notification_message" msgid="2832724384636625852">"কিছুমান কাৰ্যক্ষমতাই সঠিকভাৱে কাম নকৰিব পাৰে। নতুন ষ্ট’ৰেজ ভৰাওক।"</string>
     <string name="ext_media_unmounting_notification_title" msgid="4147986383917892162">"<xliff:g id="NAME">%s</xliff:g> বাহিৰ কৰি থকা হৈছে"</string>
     <string name="ext_media_unmounting_notification_message" msgid="5717036261538754203">"আঁতৰাই নিদিব"</string>
     <string name="ext_media_init_action" msgid="2312974060585056709">"ছেট আপ কৰক"</string>
@@ -1530,7 +1530,7 @@
       <item quantity="other"><xliff:g id="TOTAL">%d</xliff:g>ৰ <xliff:g id="INDEX">%d</xliff:g>টা</item>
     </plurals>
     <string name="action_mode_done" msgid="2536182504764803222">"সম্পন্ন হ’ল"</string>
-    <string name="progress_erasing" msgid="6891435992721028004">"শ্বেয়াৰ কৰি থোৱা সঞ্চয়াগাৰ মচি থকা হৈছে…"</string>
+    <string name="progress_erasing" msgid="6891435992721028004">"শ্বেয়াৰ কৰি থোৱা ষ্ট’ৰেজ মচি থকা হৈছে…"</string>
     <string name="share" msgid="4157615043345227321">"শ্বেয়াৰ কৰক"</string>
     <string name="find" msgid="5015737188624767706">"বিচাৰক"</string>
     <string name="websearch" msgid="5624340204512793290">"ৱেবত সন্ধান কৰক"</string>
@@ -1590,7 +1590,7 @@
     <string name="storage_sd_card_label" msgid="7526153141147470509">"<xliff:g id="MANUFACTURER">%s</xliff:g> এছডি কাৰ্ড"</string>
     <string name="storage_usb_drive" msgid="448030813201444573">"ইউএছবি ড্ৰাইভ"</string>
     <string name="storage_usb_drive_label" msgid="6631740655876540521">"<xliff:g id="MANUFACTURER">%s</xliff:g> ইউএছবি ড্ৰাইভ"</string>
-    <string name="storage_usb" msgid="2391213347883616886">"ইউএছবি সঞ্চয়াগাৰ"</string>
+    <string name="storage_usb" msgid="2391213347883616886">"ইউএছবি ষ্ট’ৰেজ"</string>
     <string name="extract_edit_menu_button" msgid="63954536535863040">"সম্পাদনা কৰক"</string>
     <string name="data_usage_warning_title" msgid="9034893717078325845">"ডেটা সকীয়নি"</string>
     <string name="data_usage_warning_body" msgid="1669325367188029454">"আপুনি <xliff:g id="APP">%s</xliff:g> ডেটা ব্যৱহাৰ কৰিছে"</string>
@@ -2022,7 +2022,7 @@
     <string name="app_category_maps" msgid="6395725487922533156">"মেপ আৰু দিক্-নিৰ্দেশনা"</string>
     <string name="app_category_productivity" msgid="1844422703029557883">"উৎপাদনশীলতা"</string>
     <string name="app_category_accessibility" msgid="6643521607848547683">"সাধ্য সুবিধা"</string>
-    <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"ডিভাইচৰ সঞ্চয়াগাৰ"</string>
+    <string name="device_storage_monitor_notification_channel" msgid="5164244565844470758">"ডিভাইচৰ ষ্ট’ৰেজ"</string>
     <string name="adb_debugging_notification_channel_tv" msgid="4764046459631031496">"ইউএছবি ডিবাগিং"</string>
     <string name="time_picker_hour_label" msgid="4208590187662336864">"ঘণ্টা"</string>
     <string name="time_picker_minute_label" msgid="8307452311269824553">"মিনিট"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index e7968e5..0219377 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -732,7 +732,7 @@
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"početak korišćenja dozvole za pregled"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Dozvoljava vlasniku da započne korišćenje dozvole za aplikaciju. Nikada ne bi trebalo da bude potrebna za uobičajene aplikacije."</string>
     <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"pokretanje prikaza funkcija aplikacije"</string>
-    <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Dozvoljava korisniku da započne pregledanje informacija o funkcijama aplikacije."</string>
+    <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Dozvoljava nosiocu dozvole da započne pregledanje informacija o funkcijama aplikacije."</string>
     <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"pristup podacima senzora pri velikoj brzini uzorkovanja"</string>
     <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Dozvoljava aplikaciji da uzima uzorak podataka senzora pri brzini većoj od 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Podešavanje pravila za lozinku"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index b06dbd9..0f47465 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -2180,7 +2180,7 @@
     <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Апавяшчэнне з інфармацыяй пра ўсталяваны рэжым"</string>
     <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Акумулятар можа разрадзіцца хутчэй, чым прыйдзе час звычайнай зарадкі"</string>
     <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Каб павялічыць тэрмін работы акумулятара, уключаны рэжым эканоміі зараду"</string>
-    <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Эканомія зараду"</string>
+    <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Рэжым энергазберажэння"</string>
     <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Рэжым эканоміі зараду выключаны"</string>
     <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"У тэлефона дастатковы ўзровень зараду. Функцыі больш не абмежаваны."</string>
     <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"У планшэта дастатковы ўзровень зараду. Функцыі больш не абмежаваны."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index e0a5363..88d6cd3 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1732,7 +1732,7 @@
     <string name="reduce_bright_colors_feature_name" msgid="3222994553174604132">"Réduction supplémentaire de la luminosité"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="5473495203759847687">"Touches de volume maintenues enfoncées. <xliff:g id="SERVICE_NAME">%1$s</xliff:g> activé."</string>
     <string name="accessibility_shortcut_disabling_service" msgid="8675244165062700619">"Touches de volume maintenues enfoncées. Service <xliff:g id="SERVICE_NAME">%1$s</xliff:g> désactivé."</string>
-    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Maintenez enfoncées les deux touches de volume pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
+    <string name="accessibility_shortcut_spoken_feedback" msgid="4228997042855695090">"Maintenez les deux touches de volume enfoncées pendant trois secondes pour utiliser <xliff:g id="SERVICE_NAME">%1$s</xliff:g>"</string>
     <string name="accessibility_button_prompt_text" msgid="8343213623338605305">"Choisissez une fonctionnalité à utiliser lorsque vous touchez le bouton d\'accessibilité :"</string>
     <string name="accessibility_gesture_prompt_text" msgid="8742535972130563952">"Choisissez une fonctionnalité à utiliser lorsque vous utilisez le geste d\'accessibilité (balayer l\'écran de bas en haut avec deux doigts) :"</string>
     <string name="accessibility_gesture_3finger_prompt_text" msgid="5211827854510660203">"Choisissez une fonctionnalité à utiliser lorsque vous utilisez le geste d\'accessibilité (balayer l\'écran de bas en haut avec trois doigts) :"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 1d9230a..7ec61f9 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1058,7 +1058,7 @@
     <string name="enable_explore_by_touch_warning_title" msgid="5095399706284943314">"छूकर, उससे जुड़ी जानकारी सुनना चालू करें?"</string>
     <string name="enable_explore_by_touch_warning_message" product="tablet" msgid="1037295476738940824">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> छूकर, उससे जुड़ी जानकारी सुनना चालू करना चाहती है. छूकर, उससे जुड़ी जानकारी सुनना चालू होने पर, जो भी आपकी उंगली के नीचे है आप उसकी जानकारी सुन या देख सकते हैं या टैबलेट के ज़रिये बातचीत करने के लिए हाथ के जेश्चर (स्पर्श) का इस्तेमाल कर सकते हैं."</string>
     <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> छूकर, उससे जुड़ी जानकारी सुनना चालू करना चाहती है. छूकर, उससे जुड़ी जानकारी सुनना चालू होने पर, जो भी आपकी उंगली के नीचे है आप उसकी जानकारी सुन या देख सकते हैं या फ़ोन के ज़रिये बातचीत करने के लिए हाथ के जेश्चर (स्पर्श) का इस्तेमाल कर सकते हैं."</string>
-    <string name="oneMonthDurationPast" msgid="4538030857114635777">"1 माह पहले"</string>
+    <string name="oneMonthDurationPast" msgid="4538030857114635777">"1 महीने पहले"</string>
     <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"1 माह से पहले"</string>
     <plurals name="last_num_days" formatted="false" msgid="687443109145393632">
       <item quantity="one">पिछले <xliff:g id="COUNT_1">%d</xliff:g> दिनों में</item>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 3dfbd06..3387fa0 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -35,7 +35,7 @@
     <string name="mmiError" msgid="2862759606579822246">"Problem s vezom ili nevažeći MMI kôd."</string>
     <string name="mmiFdnError" msgid="3975490266767565852">"Operacija je ograničena samo na brojeve s fiksnim biranjem."</string>
     <string name="mmiErrorWhileRoaming" msgid="1204173664713870114">"Nije moguće promijeniti postavke preusmjeravanja poziva na telefonu dok ste u roamingu."</string>
-    <string name="serviceEnabled" msgid="7549025003394765639">"Usluga nije omogućena."</string>
+    <string name="serviceEnabled" msgid="7549025003394765639">"Usluga je omogućena."</string>
     <string name="serviceEnabledFor" msgid="1463104778656711613">"Usluga je omogućena za korisnika:"</string>
     <string name="serviceDisabled" msgid="641878791205871379">"Usluga je onemogućena."</string>
     <string name="serviceRegistered" msgid="3856192211729577482">"Registracija je uspješna."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 71cda82..548d4ad2 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -51,8 +51,8 @@
     <string name="needPuk2" msgid="7032612093451537186">"Digita il PUK2 per sbloccare la SIM."</string>
     <string name="enablePin" msgid="2543771964137091212">"Operazione non riuscita; attiva blocco SIM/RUIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
+      <item quantity="one">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item>
       <item quantity="other">Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM venga bloccata.</item>
-      <item quantity="one">Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM venga bloccata.</item>
     </plurals>
     <string name="imei" msgid="2157082351232630390">"IMEI"</string>
     <string name="meid" msgid="3291227361605924674">"MEID"</string>
@@ -181,8 +181,8 @@
     <string name="low_memory" product="tv" msgid="6663680413790323318">"Lo spazio di archiviazione del dispositivo Android TV è pieno. Elimina alcuni file per liberare spazio."</string>
     <string name="low_memory" product="default" msgid="2539532364144025569">"Spazio di archiviazione del telefono esaurito. Elimina alcuni file per liberare spazio."</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
+      <item quantity="one">Certificate authorities installed</item>
       <item quantity="other">Autorità di certificazione installate</item>
-      <item quantity="one">Autorità di certificazione installata</item>
     </plurals>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Da una terza parte sconosciuta"</string>
     <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Dall\'amministratore del tuo profilo di lavoro"</string>
@@ -257,8 +257,8 @@
     <string name="bugreport_option_full_title" msgid="7681035745950045690">"Report completo"</string>
     <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilizza questa opzione per ridurre al minimo l\'interferenza di sistema quando il dispositivo non risponde, è troppo lento oppure quando ti servono tutte le sezioni della segnalazione. Non puoi inserire altri dettagli o acquisire altri screenshot."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206">
+      <item quantity="one">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
       <item quantity="other">Lo screenshot per la segnalazione di bug verrà acquisito tra <xliff:g id="NUMBER_1">%d</xliff:g> secondi.</item>
-      <item quantity="one">Lo screenshot per la segnalazione di bug verrà acquisito tra <xliff:g id="NUMBER_0">%d</xliff:g> secondo.</item>
     </plurals>
     <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Screenshot con segnalazione di bug effettuato correttamente"</string>
     <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"Impossibile acquisire screenshot con segnalazione di bug"</string>
@@ -1061,8 +1061,8 @@
     <string name="oneMonthDurationPast" msgid="4538030857114635777">"1 mese fa"</string>
     <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Oltre 1 mese fa"</string>
     <plurals name="last_num_days" formatted="false" msgid="687443109145393632">
+      <item quantity="one">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">Ultimi <xliff:g id="COUNT_1">%d</xliff:g> giorni</item>
-      <item quantity="one">Ultimo giorno (<xliff:g id="COUNT_0">%d</xliff:g>)</item>
     </plurals>
     <string name="last_month" msgid="1528906781083518683">"Ultimo mese"</string>
     <string name="older" msgid="1645159827884647400">"Precedente"</string>
@@ -1083,68 +1083,68 @@
     <string name="years" msgid="5797714729103773425">"anni"</string>
     <string name="now_string_shortest" msgid="3684914126941650330">"ora"</string>
     <plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest" formatted="false" msgid="2838655994500499651">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest" formatted="false" msgid="3686058472983158496">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> g</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> g</item>
     </plurals>
     <plurals name="duration_years_shortest" formatted="false" msgid="8299112348723640338">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_shortest_future" formatted="false" msgid="849196137176399440">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>m</item>
       <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> m</item>
-      <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest_future" formatted="false" msgid="5386373597343170388">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>h</item>
       <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> h</item>
-      <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest_future" formatted="false" msgid="814754627092787227">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>d</item>
       <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> g</item>
-      <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> g</item>
     </plurals>
     <plurals name="duration_years_shortest_future" formatted="false" msgid="7683731800140202145">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>y</item>
       <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> a</item>
-      <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_relative" formatted="false" msgid="6569851308583028344">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> minutes ago</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> minuti fa</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> minuto fa</item>
     </plurals>
     <plurals name="duration_hours_relative" formatted="false" msgid="420434788589102019">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> hours ago</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> ore fa</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> ora fa</item>
     </plurals>
     <plurals name="duration_days_relative" formatted="false" msgid="6056425878237482431">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> days ago</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> giorni fa</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> giorno fa</item>
     </plurals>
     <plurals name="duration_years_relative" formatted="false" msgid="2179998228861172159">
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> years ago</item>
       <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> anni fa</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> anno fa</item>
     </plurals>
     <plurals name="duration_minutes_relative_future" formatted="false" msgid="5759885720917567723">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
       <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> minuti</item>
-      <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> minuto</item>
     </plurals>
     <plurals name="duration_hours_relative_future" formatted="false" msgid="8963511608507707959">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> hours</item>
       <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> ore</item>
-      <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> ora</item>
     </plurals>
     <plurals name="duration_days_relative_future" formatted="false" msgid="1964709470979250702">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> days</item>
       <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> giorni</item>
-      <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> giorno</item>
     </plurals>
     <plurals name="duration_years_relative_future" formatted="false" msgid="3985129025134896371">
+      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> years</item>
       <item quantity="other">tra <xliff:g id="COUNT_1">%d</xliff:g> anni</item>
-      <item quantity="one">tra <xliff:g id="COUNT_0">%d</xliff:g> anno</item>
     </plurals>
     <string name="VideoView_error_title" msgid="5750686717225068016">"Problemi video"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"Questo video non è valido per lo streaming su questo dispositivo."</string>
@@ -1526,8 +1526,8 @@
     <string name="no_matches" msgid="6472699895759164599">"Nessuna corrispondenza"</string>
     <string name="find_on_page" msgid="5400537367077438198">"Trova nella pagina"</string>
     <plurals name="matches_found" formatted="false" msgid="1101758718194295554">
+      <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item>
       <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> di <xliff:g id="TOTAL">%d</xliff:g></item>
-      <item quantity="one">1 partita</item>
     </plurals>
     <string name="action_mode_done" msgid="2536182504764803222">"Fine"</string>
     <string name="progress_erasing" msgid="6891435992721028004">"Cancellazione archivio condiviso…"</string>
@@ -1659,8 +1659,8 @@
     <string name="kg_wrong_password" msgid="2384677900494439426">"Password sbagliata"</string>
     <string name="kg_wrong_pin" msgid="3680925703673166482">"PIN errato"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568">
+      <item quantity="one">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
       <item quantity="other">Riprova fra <xliff:g id="NUMBER">%d</xliff:g> secondi.</item>
-      <item quantity="one">Riprova fra 1 secondo.</item>
     </plurals>
     <string name="kg_pattern_instructions" msgid="8366024510502517748">"Inserisci la sequenza"</string>
     <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Inserisci il PIN della SIM"</string>
@@ -1859,8 +1859,8 @@
     <string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"I PIN non corrispondono. Riprova."</string>
     <string name="restr_pin_error_too_short" msgid="1547007808237941065">"Il PIN è troppo corto. Deve avere almeno quattro cifre."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
+      <item quantity="one">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
       <item quantity="other">Riprova tra <xliff:g id="COUNT">%d</xliff:g> secondi</item>
-      <item quantity="one">Riprova tra 1 secondo</item>
     </plurals>
     <string name="restr_pin_try_later" msgid="5897719962541636727">"Riprova più tardi"</string>
     <string name="immersive_cling_title" msgid="2307034298721541791">"Visualizzazione a schermo intero"</string>
@@ -1890,36 +1890,36 @@
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Attivare Risparmio dati?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Attiva"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
+      <item quantity="one">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Per %1$d minuti (fino alle ore <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="one">Per un minuto (fino alle ore <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="4230730310318858312">
+      <item quantity="one">For %1$d min (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Per %1$d minuti (fino alle ore <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="one">Per 1 minuto (fino alle ore <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758">
+      <item quantity="one">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Per %1$d ore (fino alle ore <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="one">Per 1 ora (fino alle ore <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="588719069121765642">
+      <item quantity="one">For %1$d hr (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="other">Per %1$d ore (fino alle ore <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="one">Per 1 ora (fino alle ore <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes" formatted="false" msgid="1148568456958944998">
+      <item quantity="one">For %d minutes</item>
       <item quantity="other">Per %d minuti</item>
-      <item quantity="one">Per un minuto</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2742377799995454859">
+      <item quantity="one">For %d min</item>
       <item quantity="other">Per %d minuti</item>
-      <item quantity="one">Per 1 minuto</item>
     </plurals>
     <plurals name="zen_mode_duration_hours" formatted="false" msgid="525401855645490022">
+      <item quantity="one">For %d hours</item>
       <item quantity="other">Per %d ore</item>
-      <item quantity="one">Per 1 ora</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="7644653189680911640">
+      <item quantity="one">For %d hr</item>
       <item quantity="other">Per %d ore</item>
-      <item quantity="one">Per 1 ora</item>
     </plurals>
     <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Fino a: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_until" msgid="2250286190237669079">"Fino a <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
@@ -1968,8 +1968,8 @@
     <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Chiamata in corso"</string>
     <string name="call_notification_screening_text" msgid="8396931408268940208">"Applicazione filtro a chiamata in arrivo"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> file selezionati</item>
-      <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> file selezionato</item>
     </plurals>
     <string name="default_notification_channel_label" msgid="3697928973567217330">"Senza categoria"</string>
     <string name="importance_from_user" msgid="2782756722448800447">"Stabilisci tu l\'importanza di queste notifiche."</string>
@@ -2036,8 +2036,8 @@
     <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"Impossibile compilare automaticamente i contenuti"</string>
     <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Nessun suggerimento di Compilazione automatica"</string>
     <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="6651883186966959978">
+      <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> autofill suggestions</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggerimenti di Compilazione automatica</item>
-      <item quantity="one">Un suggerimento di Compilazione automatica</item>
     </plurals>
     <string name="autofill_save_title" msgid="7719802414283739775">"Vuoi salvare su "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
     <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Vuoi salvare la <xliff:g id="TYPE">%1$s</xliff:g> su "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
@@ -2140,8 +2140,8 @@
     <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Il Bluetooth rimane attivo durante l\'uso della modalità aereo"</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"Caricamento"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
+      <item quantity="one"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> file</item>
       <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> file</item>
-      <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> file</item>
     </plurals>
     <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Nessuna persona consigliata per la condivisione"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Elenco di app"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index d5b92b7..a4e0123 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -219,7 +219,7 @@
     <string name="turn_on_radio" msgid="2961717788170634233">"უსადენო კავშირის ჩართვა"</string>
     <string name="turn_off_radio" msgid="7222573978109933360">"უსადენო ინტერნეტის გამორთვა"</string>
     <string name="screen_lock" msgid="2072642720826409809">"ეკრანის დაბლოკვა"</string>
-    <string name="power_off" msgid="4111692782492232778">"გამორთვ."</string>
+    <string name="power_off" msgid="4111692782492232778">"გამორთვა"</string>
     <string name="silent_mode_silent" msgid="5079789070221150912">"მრეკავი გათიშულია"</string>
     <string name="silent_mode_vibrate" msgid="8821830448369552678">"ვიბრაციის რეჟიმი"</string>
     <string name="silent_mode_ring" msgid="6039011004781526678">"ზარი ჩართულია"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 7006273..98ac85e 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -51,8 +51,8 @@
     <string name="needPuk2" msgid="7032612093451537186">"Introduza o PUK2 para desbloquear o cartão SIM."</string>
     <string name="enablePin" msgid="2543771964137091212">"Ação sem êxito. Ative o bloqueio do SIM/RUIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584">
-      <item quantity="other">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar bloqueado.</item>
       <item quantity="one">Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar bloqueado.</item>
+      <item quantity="other">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar bloqueado.</item>
     </plurals>
     <string name="imei" msgid="2157082351232630390">"IMEI"</string>
     <string name="meid" msgid="3291227361605924674">"MEID"</string>
@@ -181,8 +181,8 @@
     <string name="low_memory" product="tv" msgid="6663680413790323318">"O armazenamento do dispositivo Android TV está cheio. Elimine alguns ficheiros para libertar espaço."</string>
     <string name="low_memory" product="default" msgid="2539532364144025569">"O armazenamento do telemóvel está cheio. Elimine alguns ficheiros para libertar espaço."</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="2288194355006173029">
-      <item quantity="other">Autoridades de certificação instaladas</item>
       <item quantity="one">Autoridade de certificação instalada</item>
+      <item quantity="other">Autoridades de certificação instaladas</item>
     </plurals>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Por um terceiro desconhecido"</string>
     <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Pelo gestor do seu perfil de trabalho"</string>
@@ -257,8 +257,8 @@
     <string name="bugreport_option_full_title" msgid="7681035745950045690">"Relatório completo"</string>
     <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilize esta opção para uma interferência mínima do sistema quando o dispositivo não responder ou estiver demasiado lento, ou quando precisar de todas as secções de relatório. Não permite introduzir mais detalhes ou tirar capturas de ecrã adicionais."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="3906120379260059206">
-      <item quantity="other">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
       <item quantity="one">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_0">%d</xliff:g> segundo…</item>
+      <item quantity="other">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Captura de ecrã tirada com o relatório de erro."</string>
     <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"Falha ao fazer captura de ecrã com o relatório de erro."</string>
@@ -1061,8 +1061,8 @@
     <string name="oneMonthDurationPast" msgid="4538030857114635777">"Há 1 mês"</string>
     <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Há mais de 1 mês"</string>
     <plurals name="last_num_days" formatted="false" msgid="687443109145393632">
-      <item quantity="other">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
       <item quantity="one">Último <xliff:g id="COUNT_0">%d</xliff:g> dia</item>
+      <item quantity="other">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
     </plurals>
     <string name="last_month" msgid="1528906781083518683">"Último mês"</string>
     <string name="older" msgid="1645159827884647400">"Mais antiga"</string>
@@ -1083,68 +1083,68 @@
     <string name="years" msgid="5797714729103773425">"anos"</string>
     <string name="now_string_shortest" msgid="3684914126941650330">"agora"</string>
     <plurals name="duration_minutes_shortest" formatted="false" msgid="7519574894537185135">
-      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
       <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> m</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest" formatted="false" msgid="2838655994500499651">
-      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
       <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> h</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest" formatted="false" msgid="3686058472983158496">
-      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> d</item>
       <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> d</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> d</item>
     </plurals>
     <plurals name="duration_years_shortest" formatted="false" msgid="8299112348723640338">
-      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
       <item quantity="one"><xliff:g id="COUNT_0">%d</xliff:g> a</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_shortest_future" formatted="false" msgid="849196137176399440">
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> min</item>
       <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> min</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> min</item>
     </plurals>
     <plurals name="duration_hours_shortest_future" formatted="false" msgid="5386373597343170388">
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> h</item>
       <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> h</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest_future" formatted="false" msgid="814754627092787227">
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> d</item>
       <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> d</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> d</item>
     </plurals>
     <plurals name="duration_years_shortest_future" formatted="false" msgid="7683731800140202145">
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> a</item>
       <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> a</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_relative" formatted="false" msgid="6569851308583028344">
-      <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
       <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> minuto</item>
+      <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
     </plurals>
     <plurals name="duration_hours_relative" formatted="false" msgid="420434788589102019">
-      <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
       <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> hora</item>
+      <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
     </plurals>
     <plurals name="duration_days_relative" formatted="false" msgid="6056425878237482431">
-      <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
       <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> dia</item>
+      <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
     </plurals>
     <plurals name="duration_years_relative" formatted="false" msgid="2179998228861172159">
-      <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
       <item quantity="one">há <xliff:g id="COUNT_0">%d</xliff:g> ano</item>
+      <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
     </plurals>
     <plurals name="duration_minutes_relative_future" formatted="false" msgid="5759885720917567723">
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
       <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> minuto</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
     </plurals>
     <plurals name="duration_hours_relative_future" formatted="false" msgid="8963511608507707959">
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
       <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> hora</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
     </plurals>
     <plurals name="duration_days_relative_future" formatted="false" msgid="1964709470979250702">
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
       <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> dia</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
     </plurals>
     <plurals name="duration_years_relative_future" formatted="false" msgid="3985129025134896371">
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
       <item quantity="one">dentro de <xliff:g id="COUNT_0">%d</xliff:g> ano</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
     </plurals>
     <string name="VideoView_error_title" msgid="5750686717225068016">"Problema com o vídeo"</string>
     <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"Este vídeo não é válido para transmissão neste aparelho."</string>
@@ -1526,8 +1526,8 @@
     <string name="no_matches" msgid="6472699895759164599">"Sem correspondências"</string>
     <string name="find_on_page" msgid="5400537367077438198">"Localizar na página"</string>
     <plurals name="matches_found" formatted="false" msgid="1101758718194295554">
-      <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
       <item quantity="one">1 correspondência</item>
+      <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
     </plurals>
     <string name="action_mode_done" msgid="2536182504764803222">"Concluído"</string>
     <string name="progress_erasing" msgid="6891435992721028004">"A apagar o armazenamento partilhado…"</string>
@@ -1659,8 +1659,8 @@
     <string name="kg_wrong_password" msgid="2384677900494439426">"Palavra-passe Incorreta"</string>
     <string name="kg_wrong_pin" msgid="3680925703673166482">"PIN Incorreto"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="236717428673283568">
-      <item quantity="other">Tente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
       <item quantity="one">Tente novamente dentro de 1 segundo.</item>
+      <item quantity="other">Tente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="kg_pattern_instructions" msgid="8366024510502517748">"Desenhe a sua sequência"</string>
     <string name="kg_sim_pin_instructions" msgid="6479401489471690359">"Introduzir PIN do cartão SIM"</string>
@@ -1859,8 +1859,8 @@
     <string name="restr_pin_error_doesnt_match" msgid="7063392698489280556">"Os PINs não correspondem. Tente novamente."</string>
     <string name="restr_pin_error_too_short" msgid="1547007808237941065">"O PIN é demasiado pequeno. Deve ter, no mínimo, 4 dígitos."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="4427486903285216153">
-      <item quantity="other">Tente novamente dentro de <xliff:g id="COUNT">%d</xliff:g> segundos</item>
       <item quantity="one">Tente novamente dentro de 1 segundo</item>
+      <item quantity="other">Tente novamente dentro de <xliff:g id="COUNT">%d</xliff:g> segundos</item>
     </plurals>
     <string name="restr_pin_try_later" msgid="5897719962541636727">"Tente novamente mais tarde"</string>
     <string name="immersive_cling_title" msgid="2307034298721541791">"Visualização de ecrã inteiro"</string>
@@ -1890,36 +1890,36 @@
     <string name="data_saver_enable_title" msgid="7080620065745260137">"Pretende ativar a Poupança de dados?"</string>
     <string name="data_saver_enable_button" msgid="4399405762586419726">"Ativar"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="2877101784123058273">
-      <item quantity="other">Durante %1$d minutos (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="one">Durante um minuto (até à(s) <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+      <item quantity="other">Durante %1$d minutos (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="4230730310318858312">
-      <item quantity="other">Durante %1$d min (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="one">Durante 1 min (até à(s) <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+      <item quantity="other">Durante %1$d min (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="7725354244196466758">
-      <item quantity="other">Durante %1$d horas (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="one">Durante 1 hora (até à(s) <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+      <item quantity="other">Durante %1$d horas (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="588719069121765642">
-      <item quantity="other">Durante %1$d h (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
       <item quantity="one">Durante 1 h (até à(s) <xliff:g id="FORMATTEDTIME_0">%2$s</xliff:g>)</item>
+      <item quantity="other">Durante %1$d h (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes" formatted="false" msgid="1148568456958944998">
-      <item quantity="other">Durante %d minutos</item>
       <item quantity="one">Durante um minuto</item>
+      <item quantity="other">Durante %d minutos</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2742377799995454859">
-      <item quantity="other">Durante %d min</item>
       <item quantity="one">Durante 1 min</item>
+      <item quantity="other">Durante %d min</item>
     </plurals>
     <plurals name="zen_mode_duration_hours" formatted="false" msgid="525401855645490022">
-      <item quantity="other">Durante %d horas</item>
       <item quantity="one">Durante 1 hora</item>
+      <item quantity="other">Durante %d horas</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="7644653189680911640">
-      <item quantity="other">Durante %d h</item>
       <item quantity="one">Durante 1 h</item>
+      <item quantity="other">Durante %d h</item>
     </plurals>
     <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
     <string name="zen_mode_until" msgid="2250286190237669079">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
@@ -1968,8 +1968,8 @@
     <string name="call_notification_ongoing_text" msgid="3880832933933020875">"Chamada em curso"</string>
     <string name="call_notification_screening_text" msgid="8396931408268940208">"A filtrar uma chamada recebida…"</string>
     <plurals name="selected_count" formatted="false" msgid="3946212171128200491">
-      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
       <item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selecionado</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
     </plurals>
     <string name="default_notification_channel_label" msgid="3697928973567217330">"Sem categoria"</string>
     <string name="importance_from_user" msgid="2782756722448800447">"Definiu a importância destas notificações."</string>
@@ -2036,8 +2036,8 @@
     <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"Não é possível preencher automaticamente o conteúdo"</string>
     <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Sem sugestões do preenchimento automático"</string>
     <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="6651883186966959978">
-      <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugestões do preenchimento automático</item>
       <item quantity="one">Uma sugestão do preenchimento automático</item>
+      <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugestões do preenchimento automático</item>
     </plurals>
     <string name="autofill_save_title" msgid="7719802414283739775">"Pretende guardar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
     <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Pretende guardar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
@@ -2140,8 +2140,8 @@
     <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"O Bluetooth continuará ativado durante o modo de avião."</string>
     <string name="car_loading_profile" msgid="8219978381196748070">"A carregar…"</string>
     <plurals name="file_count" formatted="false" msgid="7063513834724389247">
-      <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ficheiros</item>
       <item quantity="one"><xliff:g id="FILE_NAME_0">%s</xliff:g> + <xliff:g id="COUNT_1">%d</xliff:g> ficheiro</item>
+      <item quantity="other"><xliff:g id="FILE_NAME_2">%s</xliff:g> + <xliff:g id="COUNT_3">%d</xliff:g> ficheiros</item>
     </plurals>
     <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Não existem pessoas recomendadas com quem partilhar"</string>
     <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Lista de aplicações"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index a6f8257..c14dd45 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -223,7 +223,7 @@
     <string name="turn_on_radio" msgid="2961717788170634233">"Vklopi brezžično omrežje"</string>
     <string name="turn_off_radio" msgid="7222573978109933360">"Izklopi brezžično omrežje"</string>
     <string name="screen_lock" msgid="2072642720826409809">"Zaklep zaslona"</string>
-    <string name="power_off" msgid="4111692782492232778">"Izklopi"</string>
+    <string name="power_off" msgid="4111692782492232778">"Izklop"</string>
     <string name="silent_mode_silent" msgid="5079789070221150912">"Izklopi zvonjenje"</string>
     <string name="silent_mode_vibrate" msgid="8821830448369552678">"Zvonjenje z vibriranjem"</string>
     <string name="silent_mode_ring" msgid="6039011004781526678">"Vklopi zvonjenje"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b04ddaf..04fed0c 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -732,7 +732,7 @@
     <string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"почетак коришћења дозволе за преглед"</string>
     <string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Дозвољава власнику да започне коришћење дозволе за апликацију. Никада не би требало да буде потребна за уобичајене апликације."</string>
     <string name="permlab_startViewAppFeatures" msgid="7955084203185903001">"покретање приказа функција апликације"</string>
-    <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Дозвољава кориснику да започне прегледање информација о функцијама апликације."</string>
+    <string name="permdesc_startViewAppFeatures" msgid="7207240860165206107">"Дозвољава носиоцу дозволе да започне прегледање информација о функцијама апликације."</string>
     <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"приступ подацима сензора при великој брзини узорковања"</string>
     <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Дозвољава апликацији да узима узорак података сензора при брзини већој од 200 Hz"</string>
     <string name="policylab_limitPassword" msgid="4851829918814422199">"Подешавање правила за лозинку"</string>
diff --git a/core/res/res/values-sw600dp/config.xml b/core/res/res/values-sw600dp/config.xml
index 861e329..34b6a54 100644
--- a/core/res/res/values-sw600dp/config.xml
+++ b/core/res/res/values-sw600dp/config.xml
@@ -51,10 +51,5 @@
 
     <!-- If true, show multiuser switcher by default unless the user specifically disables it. -->
     <bool name="config_showUserSwitcherByDefault">true</bool>
-
-    <!-- Enable dynamic keyguard positioning for large-width screens. This will cause the keyguard
-         to be aligned to one side of the screen when in landscape mode. -->
-    <bool name="config_enableDynamicKeyguardPositioning">true</bool>
-
 </resources>
 
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index c3e5a66..e8dbf3c 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -90,12 +90,12 @@
     <string name="notification_channel_network_alert" msgid="4788053066033851841">"అలర్ట్‌లు"</string>
     <string name="notification_channel_call_forward" msgid="8230490317314272406">"కాల్ ఫార్వార్డింగ్"</string>
     <string name="notification_channel_emergency_callback" msgid="54074839059123159">"అత్యవసర కాల్‌బ్యాక్ మోడ్"</string>
-    <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"మొబైల్ డేటా స్థితి"</string>
+    <string name="notification_channel_mobile_data_status" msgid="1941911162076442474">"మొబైల్ డేటా స్టేటస్‌"</string>
     <string name="notification_channel_sms" msgid="1243384981025535724">"SMS మెసేజ్‌లు"</string>
     <string name="notification_channel_voice_mail" msgid="8457433203106654172">"వాయిస్ మెయిల్ మెసేజ్‌లు"</string>
     <string name="notification_channel_wfc" msgid="9048240466765169038">"Wi-Fi కాలింగ్"</string>
     <string name="notification_channel_sim" msgid="5098802350325677490">"SIM స్టేటస్"</string>
-    <string name="notification_channel_sim_high_prio" msgid="642361929452850928">"అధిక ప్రాధాన్యత గల SIM స్థితి"</string>
+    <string name="notification_channel_sim_high_prio" msgid="642361929452850928">"అధిక ప్రాధాన్యత గల SIM స్టేటస్‌"</string>
     <string name="peerTtyModeFull" msgid="337553730440832160">"అవతలి వారు FULL TTY మోడ్‌ని అభ్యర్థించారు"</string>
     <string name="peerTtyModeHco" msgid="5626377160840915617">"అవతలి వారు HCO TTY మోడ్‌ని అభ్యర్థించారు"</string>
     <string name="peerTtyModeVco" msgid="572208600818270944">"అవతలి వారు VCO TTY మోడ్‌ని అభ్యర్థించారు"</string>
@@ -278,14 +278,14 @@
     <string name="notification_channel_physical_keyboard" msgid="5417306456125988096">"భౌతిక కీబోర్డ్"</string>
     <string name="notification_channel_security" msgid="8516754650348238057">"సెక్యూరిటీ"</string>
     <string name="notification_channel_car_mode" msgid="2123919247040988436">"కార్‌ మోడ్"</string>
-    <string name="notification_channel_account" msgid="6436294521740148173">"ఖాతా స్థితి"</string>
+    <string name="notification_channel_account" msgid="6436294521740148173">"ఖాతా స్టేటస్‌"</string>
     <string name="notification_channel_developer" msgid="1691059964407549150">"డెవలపర్ మెసేజ్‌లు"</string>
     <string name="notification_channel_developer_important" msgid="7197281908918789589">"ముఖ్యమైన డెవలపర్ మెసేజ్‌లు"</string>
     <string name="notification_channel_updates" msgid="7907863984825495278">"అప్‌డేట్‌లు"</string>
-    <string name="notification_channel_network_status" msgid="2127687368725272809">"నెట్‌వర్క్ స్థితి"</string>
+    <string name="notification_channel_network_status" msgid="2127687368725272809">"నెట్‌వర్క్ స్టేటస్‌"</string>
     <string name="notification_channel_network_alerts" msgid="6312366315654526528">"నెట్‌వర్క్ హెచ్చరికలు"</string>
     <string name="notification_channel_network_available" msgid="6083697929214165169">"నెట్‌వర్క్ అందుబాటులో ఉంది"</string>
-    <string name="notification_channel_vpn" msgid="1628529026203808999">"VPN స్థితి"</string>
+    <string name="notification_channel_vpn" msgid="1628529026203808999">"VPN స్టేటస్‌"</string>
     <string name="notification_channel_device_admin" msgid="6384932669406095506">"మీ IT నిర్వాహకుల నుండి వచ్చే హెచ్చరికలు"</string>
     <string name="notification_channel_alerts" msgid="5070241039583668427">"అలర్ట్‌లు"</string>
     <string name="notification_channel_retail_mode" msgid="3732239154256431213">"రిటైల్ డెమో"</string>
@@ -342,12 +342,12 @@
     <string name="capability_desc_canCaptureFingerprintGestures" msgid="6861869337457461274">"పరికర వేలిముద్ర సెన్సార్‌లో ఉపయోగించిన సంజ్ఞలను క్యాప్చర్ చేయవచ్చు."</string>
     <string name="capability_title_canTakeScreenshot" msgid="3895812893130071930">"స్క్రీన్‌షాట్‌ను తీయండి"</string>
     <string name="capability_desc_canTakeScreenshot" msgid="7762297374317934052">"డిస్‌ప్లే యొక్క స్క్రీన్‌షాట్ తీసుకోవచ్చు."</string>
-    <string name="permlab_statusBar" msgid="8798267849526214017">"స్థితి బార్‌ను నిలిపివేయడం లేదా సవరించడం"</string>
-    <string name="permdesc_statusBar" msgid="5809162768651019642">"స్థితి బార్‌ను నిలిపివేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
-    <string name="permlab_statusBarService" msgid="2523421018081437981">"స్థితి పట్టీగా ఉండటం"</string>
-    <string name="permdesc_statusBarService" msgid="6652917399085712557">"స్థితి బార్‌ ఉండేలా చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
-    <string name="permlab_expandStatusBar" msgid="1184232794782141698">"స్థితి పట్టీని విస్తరింపజేయడం/కుదించడం"</string>
-    <string name="permdesc_expandStatusBar" msgid="7180756900448498536">"స్థితి బార్‌ను విస్తరింపజేయడానికి లేదా కుదించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permlab_statusBar" msgid="8798267849526214017">"స్టేటస్‌ బార్‌ను డిజేబుల్ చేయడం లేదా మార్చడం"</string>
+    <string name="permdesc_statusBar" msgid="5809162768651019642">"స్టేటస్‌ బార్‌ను డిజేబుల్ చేయడానికి లేదా సిస్టమ్ చిహ్నాలను జోడించడానికి మరియు తీసివేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permlab_statusBarService" msgid="2523421018081437981">"స్టేటస్‌ పట్టీగా ఉండటం"</string>
+    <string name="permdesc_statusBarService" msgid="6652917399085712557">"స్టేటస్‌ బార్‌ ఉండేలా చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
+    <string name="permlab_expandStatusBar" msgid="1184232794782141698">"స్టేటస్‌ పట్టీని విస్తరింపజేయడం/కుదించడం"</string>
+    <string name="permdesc_expandStatusBar" msgid="7180756900448498536">"స్టేటస్‌ బార్‌ను విస్తరింపజేయడానికి లేదా కుదించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_fullScreenIntent" msgid="4310888199502509104">"లాక్ చేసి ఉన్న పరికరంలో నోటిఫికేషన్‌లను ఫుల్ స్క్రీన్ యాక్టివిటీలుగా డిస్‌ప్లే చేస్తుంది"</string>
     <string name="permdesc_fullScreenIntent" msgid="1100721419406643997">"లాక్ చేసి ఉన్న పరికరంలో నోటిఫికేషన్‌లను ఫుల్ స్క్రీన్ యాక్టివిటీలుగా డిస్‌ప్లే చేయడానికి యాప్‌ను అనుమతిస్తుంది"</string>
     <string name="permlab_install_shortcut" msgid="7451554307502256221">"షార్ట్‌కట్‌లను ఇన్‌స్టాల్ చేయడం"</string>
@@ -469,7 +469,7 @@
     <string name="permdesc_callPhone" msgid="5439809516131609109">"మీ ప్రమేయం లేకుండా ఫోన్ నంబర్‌లకు కాల్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. దీని వలన అనుకోని ఛార్జీలు విధించబడవచ్చు లేదా కాల్స్‌ రావచ్చు. ఇది అత్యవసర నంబర్‌లకు కాల్ చేయడానికి యాప్‌ను అనుమతించదని గుర్తుంచుకోండి. హానికరమైన యాప్‌లు మీ నిర్ధారణ లేకుండానే కాల్స్‌ చేయడం ద్వారా మీకు డబ్బు ఖర్చయ్యేలా చేయవచ్చు."</string>
     <string name="permlab_accessImsCallService" msgid="442192920714863782">"IMS కాల్ సేవ యాక్సెస్ అనుమతి"</string>
     <string name="permdesc_accessImsCallService" msgid="6328551241649687162">"మీ ప్రమేయం లేకుండా కాల్స్‌ చేయడం కోసం IMS సేవను ఉపయోగించడానికి యాప్‌ను అనుమతిస్తుంది."</string>
-    <string name="permlab_readPhoneState" msgid="8138526903259297969">"ఫోన్ స్థితి మరియు గుర్తింపుని చదవడం"</string>
+    <string name="permlab_readPhoneState" msgid="8138526903259297969">"ఫోన్ స్టేటస్‌ మరియు గుర్తింపుని చదవడం"</string>
     <string name="permdesc_readPhoneState" msgid="7229063553502788058">"పరికరం యొక్క ఫోన్ ఫీచర్‌లను యాక్సెస్ చేయడానికి యాప్‌ను అనుమతిస్తుంది. ఈ అనుమతి ఫోన్ నంబర్ మరియు పరికరం IDలను, కాల్ సక్రియంగా ఉందా లేదా అనే విషయాన్ని మరియు కాల్ ద్వారా కనెక్ట్ చేయబడిన రిమోట్ నంబర్‌ను కనుగొనడానికి యాప్‌ను అనుమతిస్తుంది."</string>
     <string name="permlab_manageOwnCalls" msgid="9033349060307561370">"కాల్స్‌ను సిస్టమ్ ద్వారా వెళ్లేలా చేయి"</string>
     <string name="permdesc_manageOwnCalls" msgid="4431178362202142574">"కాలింగ్ అనుభవాన్ని మెరుగుపరచడం కోసం తన కాల్స్‌ను సిస్టమ్ ద్వారా వెళ్లేలా చేయడానికి యాప్‌ను అనుమతిస్తుంది."</string>
@@ -716,7 +716,7 @@
     <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"టచ్ స్క్రీన్ యొక్క క్రమాంకన పరామితులను సవరించడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ అవసరం ఉండదు."</string>
     <string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"DRM ప్రమాణపత్రాలను యాక్సెస్ చేయడం"</string>
     <string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"DRM ప్రమాణపత్రాలను కేటాయించడానికి మరియు ఉపయోగించడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ అవసరం ఉండదు."</string>
-    <string name="permlab_handoverStatus" msgid="7620438488137057281">"Android Beam బదిలీ స్థితిని స్వీకరించడం"</string>
+    <string name="permlab_handoverStatus" msgid="7620438488137057281">"Android Beam బదిలీ స్టేటస్‌ని స్వీకరించడం"</string>
     <string name="permdesc_handoverStatus" msgid="3842269451732571070">"ప్రస్తుత Android Beam బదిలీలకు సంబంధించిన సమాచారాన్ని స్వీకరించడానికి ఈ యాప్‌ను అనుమతిస్తుంది"</string>
     <string name="permlab_removeDrmCertificates" msgid="710576248717404416">"DRM ప్రమాణపత్రాలను తీసివేయడం"</string>
     <string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"DRM ప్రమాణపత్రాలను తీసివేయడానికి యాప్‌ను అనుమతిస్తుంది. సాధారణ యాప్‌లకు ఎప్పటికీ అవసరం ఉండదు."</string>
@@ -959,7 +959,7 @@
     <string name="keyguard_accessibility_unlock_area_collapsed" msgid="4729922043778400434">"అన్‌లాక్ ప్రాంతం కుదించబడింది."</string>
     <string name="keyguard_accessibility_widget" msgid="6776892679715699875">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> విడ్జెట్."</string>
     <string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"వినియోగదారు ఎంపికకర్త"</string>
-    <string name="keyguard_accessibility_status" msgid="6792745049712397237">"స్థితి"</string>
+    <string name="keyguard_accessibility_status" msgid="6792745049712397237">"స్టేటస్‌"</string>
     <string name="keyguard_accessibility_camera" msgid="7862557559464986528">"కెమెరా"</string>
     <string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"మీడియా నియంత్రణలు"</string>
     <string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"విడ్జెట్ పునఃక్రమం ప్రారంభించబడింది."</string>
@@ -1204,9 +1204,9 @@
     <string name="whichOpenLinksWithApp" msgid="6917864367861910086">"<xliff:g id="APPLICATION">%1$s</xliff:g>తో లింక్‌లను తెరవండి"</string>
     <string name="whichOpenHostLinksWithApp" msgid="2401668560768463004">"<xliff:g id="HOST">%1$s</xliff:g> లింక్‌లను <xliff:g id="APPLICATION">%2$s</xliff:g>తో తెరవండి"</string>
     <string name="whichGiveAccessToApplicationLabel" msgid="7805857277166106236">"యాక్సెస్ ఇవ్వండి"</string>
-    <string name="whichEditApplication" msgid="6191568491456092812">"దీనితో సవరించు"</string>
-    <string name="whichEditApplicationNamed" msgid="8096494987978521514">"%1$sతో సవరించు"</string>
-    <string name="whichEditApplicationLabel" msgid="1463288652070140285">"సవరించు"</string>
+    <string name="whichEditApplication" msgid="6191568491456092812">"దీనితో ఎడిట్ చేయండి"</string>
+    <string name="whichEditApplicationNamed" msgid="8096494987978521514">"%1$sతో ఎడిట్ చేయండి"</string>
+    <string name="whichEditApplicationLabel" msgid="1463288652070140285">"ఎడిట్"</string>
     <string name="whichSendApplication" msgid="4143847974460792029">"షేర్ చేయండి"</string>
     <string name="whichSendApplicationNamed" msgid="4470386782693183461">"%1$sతో షేర్ చేయండి"</string>
     <string name="whichSendApplicationLabel" msgid="7467813004769188515">"షేర్ చేయి"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 7fb0b7b..e16d100 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -202,7 +202,7 @@
     <string name="location_changed_notification_text" msgid="7158423339982706912">"Дізнатися більше можна в IT-адміністратора"</string>
     <string name="geofencing_service" msgid="3826902410740315456">"Сервіс геозонування"</string>
     <string name="country_detector" msgid="7023275114706088854">"Визначення країни"</string>
-    <string name="location_service" msgid="2439187616018455546">"Служби локації"</string>
+    <string name="location_service" msgid="2439187616018455546">"Геолокація"</string>
     <string name="gnss_service" msgid="8907781262179951385">"Сервіс GNSS"</string>
     <string name="sensor_notification_service" msgid="7474531979178682676">"Сервіс \"Сповіщення датчика\""</string>
     <string name="twilight_service" msgid="8964898045693187224">"Сервіс \"Сутінки\""</string>
diff --git a/core/res/res/values-w198dp/dimens_material.xml b/core/res/res/values-w198dp/dimens_material.xml
new file mode 100644
index 0000000..a8aed25
--- /dev/null
+++ b/core/res/res/values-w198dp/dimens_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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="screen_percentage_05">9.9dp</dimen>
+    <dimen name="screen_percentage_10">19.8dp</dimen>
+    <dimen name="screen_percentage_15">29.7dp</dimen>
+</resources>
diff --git a/core/res/res/values-w208dp/dimens_material.xml b/core/res/res/values-w208dp/dimens_material.xml
new file mode 100644
index 0000000..069eeb0
--- /dev/null
+++ b/core/res/res/values-w208dp/dimens_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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="screen_percentage_05">10.4dp</dimen>
+    <dimen name="screen_percentage_10">20.8dp</dimen>
+    <dimen name="screen_percentage_15">31.2dp</dimen>
+</resources>
diff --git a/core/res/res/values-w211dp/dimens_material.xml b/core/res/res/values-w211dp/dimens_material.xml
new file mode 100644
index 0000000..bd7ca9a
--- /dev/null
+++ b/core/res/res/values-w211dp/dimens_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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="screen_percentage_05">10.55dp</dimen>
+    <dimen name="screen_percentage_10">21.1dp</dimen>
+    <dimen name="screen_percentage_15">31.65dp</dimen>
+</resources>
diff --git a/core/res/res/values-w227dp/dimens_material.xml b/core/res/res/values-w227dp/dimens_material.xml
new file mode 100644
index 0000000..eb4df8a2
--- /dev/null
+++ b/core/res/res/values-w227dp/dimens_material.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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="screen_percentage_05">11.35dp</dimen>
+    <dimen name="screen_percentage_10">22.7dp</dimen>
+    <dimen name="screen_percentage_15">34.05dp</dimen>
+</resources>
diff --git a/core/res/res/values-watch/colors.xml b/core/res/res/values-watch/colors.xml
index 854fbfd..6d908be 100644
--- a/core/res/res/values-watch/colors.xml
+++ b/core/res/res/values-watch/colors.xml
@@ -17,6 +17,6 @@
 
 <resources>
     <!-- Wear Material standard colors -->
-    <color name="wear_material_red_400">#EE675C</color>
+    <color name="wear_material_red_mid">#CC5D58</color>
     <color name="wear_material_grey_900">#202124</color>
 </resources>
\ No newline at end of file
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
index cd809b8..cf0488b 100644
--- a/core/res/res/values-watch/config.xml
+++ b/core/res/res/values-watch/config.xml
@@ -27,10 +27,6 @@
         <item>restart</item>
     </string-array>
 
-    <!-- Base "touch slop" value used by ViewConfiguration as a
-         movement threshold where scrolling should begin. -->
-    <dimen name="config_viewConfigurationTouchSlop">4dp</dimen>
-
     <!-- Minimum velocity to initiate a fling, as measured in dips per second. -->
     <dimen name="config_viewMinFlingVelocity">500dp</dimen>
 
diff --git a/core/res/res/values-watch/donottranslate.xml b/core/res/res/values-watch/donottranslate.xml
index d247ff6..f328def 100644
--- a/core/res/res/values-watch/donottranslate.xml
+++ b/core/res/res/values-watch/donottranslate.xml
@@ -17,6 +17,6 @@
 <resources>
     <!-- DO NOT TRANSLATE Spans within this text are applied to style composing regions
     within an EditText widget. The text content is ignored and not used.
-    Note: This is @color/material_deep_teal_200, cannot use @color references here. -->
-    <string name="candidates_style" translatable="false"><font color="#80cbc4">candidates</font></string>
+    Note: This is @color/GM2_blue_300, cannot use @color references here. -->
+    <string name="candidates_style" translatable="false"><font color="#8AB4F8">candidates</font></string>
  </resources>
diff --git a/core/res/res/values-watch/strings.xml b/core/res/res/values-watch/strings.xml
index 57c136e..4d4ce1e 100644
--- a/core/res/res/values-watch/strings.xml
+++ b/core/res/res/values-watch/strings.xml
@@ -25,8 +25,12 @@
         <xliff:g id="number" example="123">%2$d</xliff:g>.</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. Override from base which says "Body Sensors". [CHAR_LIMIT=25] -->
-<string name="permgrouplab_sensors">Sensors</string>
+    <string name="permgrouplab_sensors">Sensors</string>
 
 
     <!-- label for item that opens emergency features in the power menu on Wear [CHAR LIMIT=24] -->
-    <string name="global_action_emergency">Emergency SOS</string></resources>
+    <string name="global_action_emergency">Emergency SOS</string>
+
+   <!-- Reboot to Recovery Progress Dialog. This is shown before it reboots to recovery. -->
+    <string name="reboot_to_update_title">Wear OS system update</string>
+</resources>
\ No newline at end of file
diff --git a/core/res/res/values-watch/styles_device_default.xml b/core/res/res/values-watch/styles_device_default.xml
new file mode 100644
index 0000000..e2261af
--- /dev/null
+++ b/core/res/res/values-watch/styles_device_default.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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>
+    <style name="DialogWindowTitle.DeviceDefault" parent="DialogWindowTitle.Material">
+      <item name="maxLines">2</item>
+      <item name="shadowRadius">0</item>
+      <item name="ellipsize">end</item>
+      <item name="textAppearance">@style/TextAppearance.DeviceDefault.Title</item>
+    </style>
+    <style name="TextAppearance.DeviceDefault.Body1" parent="TextAppearance.Material.Body1">
+        <item name="android:textSize">15sp</item>
+        <item name="android:fontFamily">sans-serif</item>
+    </style>
+    <style name="TextAppearance.DeviceDefault.Title" parent="TextAppearance.Material.Title">
+        <item name="android:textSize">16sp</item>
+        <item name="android:fontFamily">google-sans</item>
+        <item name="android:textStyle">bold</item>
+    </style>
+    <style name="TextAppearance.DeviceDefault.Subhead" parent="TextAppearance.Material.Subhead">
+        <item name="android:textSize">16sp</item>
+        <item name="android:fontFamily">google-sans-medium</item>
+    </style>
+</resources>
diff --git a/core/res/res/values-watch/themes_device_defaults.xml b/core/res/res/values-watch/themes_device_defaults.xml
index 8c50344..1db006f 100644
--- a/core/res/res/values-watch/themes_device_defaults.xml
+++ b/core/res/res/values-watch/themes_device_defaults.xml
@@ -44,6 +44,7 @@
         <item name="colorBackgroundCacheHint">@color/background_cache_hint_selector_device_default</item>
         <item name="colorButtonNormal">@color/button_normal_device_default_dark</item>
         <item name="colorError">@color/error_color_device_default_dark</item>
+        <item name="colorEdgeEffect">@color/white</item>
         <item name="disabledAlpha">@dimen/disabled_alpha_device_default</item>
         <item name="primaryContentAlpha">@dimen/primary_content_alpha_device_default</item>
         <item name="secondaryContentAlpha">@dimen/secondary_content_alpha_device_default</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 819857f..697ec20 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5383,6 +5383,16 @@
             <!-- Standard amount of hyphenation, useful for running text and for
             screens with limited space for text. -->
             <enum name="full" value="2" />
+
+            <!-- Same to hyphenationFrequency="normal" but using faster algorithm for measuring
+            hyphenation break points. To make text rendering faster with hyphenation, this algorithm
+             ignores some hyphen character related typographic features, e.g. kerning. -->
+            <enum name="normalFast" value="3" />
+
+            <!-- Same to hyphenationFrequency="full" but using faster algorithm for measuring
+            hyphenation break points. To make text rendering faster with hyphenation, this algorithm
+             ignores some hyphen character related typographic features, e.g. kerning. -->
+            <enum name="fullFast" value="4" />
         </attr>
         <!-- Specify the type of auto-size. Note that this feature is not supported by EditText,
         works only for TextView. -->
@@ -9316,6 +9326,18 @@
         <attr name="canPauseRecording" format="boolean" />
     </declare-styleable>
 
+    <!-- Use <code>tv-iapp</code> as the root tag of the XML resource that describes a
+         {@link android.media.tv.interactive.TvIAppService}, which is referenced from its
+         {@link android.media.tv.interactive.TvIAppService#SERVICE_META_DATA} meta-data entry.
+         Described here are the attributes that can be included in that tag. -->
+    <declare-styleable name="TvIAppService">
+        <!-- The interactive app types that the TV interactive app service supports.
+             Reference to a string array resource that describes the supported types,
+             e.g. HbbTv, Ginga. -->
+        <attr name="supportedTypes" format="reference" />
+    </declare-styleable>
+
+
     <!-- Attributes that can be used with <code>rating-system-definition</code> tags inside of the
          XML resource that describes TV content rating of a {@link android.media.tv.TvInputService},
          which is referenced from its
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 7805d46..94717b1 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1991,6 +1991,12 @@
 
         <!-- Whether attributions provided are meant to be user-visible. -->
         <attr name="attributionsAreUserVisible" format="boolean" />
+
+        <!-- Specifies whether enabled settings of components in the application should be
+             reset to {@link android.content.pm.PackageManager#COMPONENT_ENABLED_STATE_DEFAULT}
+             when the application's user data is cleared. The default value is false.
+        -->
+        <attr name="resetEnabledSettingsOnAppDataCleared" format="boolean" />
     </declare-styleable>
 
     <!-- An attribution is a logical part of an app and is identified by a tag.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 81fada3..2b830b4 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -654,10 +654,23 @@
         -->
     </integer-array>
 
-    <!-- When entering this device state (defined in device_state_configuration.xml),
-         we should wake the device. -1 to disable the feature (do not wake on any device-state
-         transition). -->
-    <integer name="config_deviceStateOnWhichToWakeUp">-1</integer>
+    <!-- When a device enters any of these states, it should be woken up. States are defined in
+         device_state_configuration.xml. -->
+    <integer-array name="config_deviceStatesOnWhichToWakeUp">
+        <!-- Example:
+        <item>0</item>
+        <item>1</item>
+        -->
+    </integer-array>
+
+    <!-- When a device enters any of these states, it should go to sleep. States are defined in
+         device_state_configuration.xml. -->
+    <integer-array name="config_deviceStatesOnWhichToSleep">
+        <!-- Example:
+        <item>0</item>
+        <item>1</item>
+        -->
+    </integer-array>
 
     <!-- Indicate the display area rect for foldable devices in folded state. -->
     <string name="config_foldedArea"></string>
@@ -1406,6 +1419,12 @@
     <integer name="config_screenBrightnessDim">10</integer>
     <item name="config_screenBrightnessDimFloat" format="float" type="dimen">0.05</item>
 
+    <!-- If the screen brightness is already set at or below config_screenBrightnessDim, and the
+         user activity timeout expires, we still want to dim the screen slightly to indicate that
+         the device is about to go to sleep. The screen will dim by this amount in that case.
+         -->
+    <item name="config_screenBrightnessMinimumDimAmountFloat" format="float" type="dimen">0.04</item>
+
     <!-- Minimum allowable screen brightness to use in a very dark room.
          This value sets the floor for the darkest possible auto-brightness
          adjustment.  It is expected to be somewhat less than the first entry in
@@ -1464,6 +1483,30 @@
     <integer-array name="config_autoBrightnessLevels">
     </integer-array>
 
+    <!-- Array of light sensor lux values to define our levels for auto backlight brightness
+         support whilst in idle mode.
+         The N entries of this array define N + 1 control points as follows:
+         (1-based arrays)
+
+         Point 1:            (0, value[1]):             lux <= 0
+         Point 2:     (level[1], value[2]):  0        < lux <= level[1]
+         Point 3:     (level[2], value[3]):  level[2] < lux <= level[3]
+         ...
+         Point N+1: (level[N], value[N+1]):  level[N] < lux
+
+         The control points must be strictly increasing. Each control point
+         corresponds to an entry in the brightness backlight values arrays.
+         For example, if lux == level[1] (first element of the levels array)
+         then the brightness will be determined by value[2] (second element
+         of the brightness values array).
+
+         Spline interpolation is used to determine the auto-brightness
+         backlight values for lux levels between these control points.
+
+         Must be overridden in platform specific overlays -->
+    <integer-array name="config_autoBrightnessLevelsIdle">
+    </integer-array>
+
     <!-- Timeout (in milliseconds) after which we remove the effects any user interactions might've
          had on the brightness mapping. This timeout doesn't start until we transition to a
          non-interactive display policy so that we don't reset while users are using their devices,
@@ -1487,6 +1530,10 @@
     <integer-array name="config_autoBrightnessLcdBacklightValues_doze">
     </integer-array>
 
+    <!-- Enables idle screen brightness mode on this device.
+         If this is true, config_autoBrightnessDisplayValuesNitsIdle must be defined. -->
+    <bool name="config_enableIdleScreenBrightnessMode">false</bool>
+
     <!-- Array of desired screen brightness in nits corresponding to the lux values
          in the config_autoBrightnessLevels array. As with config_screenBrightnessMinimumNits and
          config_screenBrightnessMaximumNits, the display brightness is defined as the measured
@@ -1503,6 +1550,13 @@
     <array name="config_autoBrightnessDisplayValuesNits">
     </array>
 
+    <!-- Array of desired screen brightness in nits for idle screen brightness mode.
+         This array should meet the same requirements as config_autoBrightnessDisplayValuesNits.
+         This array also corresponds to the lux values given in config_autoBrightnessLevelsIdle.
+         In order to activate this mode, config_enableIdleScreenBrightnessMode must be true. -->
+    <array name="config_autoBrightnessDisplayValuesNitsIdle">
+    </array>
+
     <!-- Array of output values for button backlight corresponding to the luX values
          in the config_autoBrightnessLevels array.  This array should have size one greater
          than the size of the config_autoBrightnessLevels array.
@@ -1748,6 +1802,13 @@
          provider services. -->
     <string name="config_secondaryLocationTimeZoneProviderPackageName" translatable="false"></string>
 
+    <!-- Whether the time zone detection logic supports fall back from geolocation suggestions to
+         telephony suggestions temporarily in certain circumstances. Reduces time zone detection
+         latency during some scenarios like air travel. Only useful when both geolocation and
+         telephony time zone detection are supported on a device.
+         See com.android.server.timezonedetector.TimeZoneDetectorStrategy for more information. -->
+    <bool name="config_supportTelephonyTimeZoneFallback" translatable="false">false</bool>
+
     <!-- Whether to enable network location overlay which allows network location provider to be
          replaced by an app at run-time. When disabled, only the
          config_networkLocationProviderPackageName package will be searched for network location
@@ -4924,9 +4985,10 @@
          the app in the letterbox mode. -->
     <item name="config_fixedOrientationLetterboxAspectRatio" format="float" type="dimen">0.0</item>
 
-    <!-- Corners radius for activity presented the letterbox mode. Values < 0 will be ignored and
-         min between device bottom corner radii will be used instead. -->
-    <integer name="config_letterboxActivityCornersRadius">-1</integer>
+    <!-- Corners radius for activity presented the letterbox mode. Values < 0 enable rounded
+         corners with radius equal to min between device bottom corner radii. Default 0 value turns
+         off rounded corners logic in LetterboxUiController. -->
+    <integer name="config_letterboxActivityCornersRadius">0</integer>
 
     <!-- Blur radius for the Option 3 in R.integer.config_letterboxBackgroundType. Values < 0 are
         ignored and 0 is used. -->
@@ -5025,10 +5087,6 @@
     <!-- Whether to select voice/data/sms preference without user confirmation -->
     <bool name="config_voice_data_sms_auto_fallback">false</bool>
 
-    <!-- Whether to enable dynamic keyguard positioning for wide screen devices (e.g. only using
-         half of the screen, to be accessible using only one hand). -->
-    <bool name="config_enableDynamicKeyguardPositioning">false</bool>
-
     <!-- Whether to allow the caching of the SIM PIN for verification after unattended reboot -->
     <bool name="config_allow_pin_storage_for_unattended_reboot">true</bool>
 
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 2820f86..dc548b9 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3304,6 +3304,8 @@
     <public name="requiredSplitTypes" />
     <public name="splitTypes" />
     <public name="canDisplayOnRemoteDevices" />
+    <public name="supportedTypes" />
+    <public name="resetEnabledSettingsOnAppDataCleared" />
   </staging-public-group>
 
   <staging-public-group type="id" first-id="0x01de0000">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 192f5c0..f6a0e61 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2027,6 +2027,10 @@
     typed when unlocking the screen, and lock your Android TV device or erase all your Android TV device\'s
     data if too many incorrect passwords are typed.</string>
     <!-- Description of policy access to watch user login attempts -->
+    <string name="policydesc_watchLogin" product="automotive">Monitor the number of incorrect passwords
+    typed. when unlocking the screen, and lock the infotainment system or erase all the infotainment system\'s
+    data if too many incorrect passwords are typed.</string>
+    <!-- Description of policy access to watch user login attempts -->
     <string name="policydesc_watchLogin" product="default">Monitor the number of incorrect passwords
     typed. when unlocking the screen, and lock the phone or erase all the phone\'s
     data if too many incorrect passwords are typed.</string>
@@ -2036,6 +2040,9 @@
     <string name="policydesc_watchLogin_secondaryUser" product="tv">Monitor the number of incorrect passwords
     typed when unlocking the screen, and lock your Android TV device or erase all this user\'s data
     if too many incorrect passwords are typed.</string>
+    <string name="policydesc_watchLogin_secondaryUser" product="automotive">Monitor the number of incorrect passwords
+    typed when unlocking the screen, and lock the infotainment system or erase all this profile\'s data
+    if too many incorrect passwords are typed.</string>
     <string name="policydesc_watchLogin_secondaryUser" product="default">Monitor the number of incorrect passwords
     typed when unlocking the screen, and lock the phone or erase all this user\'s data
     if too many incorrect passwords are typed.</string>
@@ -2054,14 +2061,20 @@
     <!-- Description of policy access to wipe the user's data -->
     <string name="policydesc_wipeData" product="tv">Erase your Android TV device\'s data without warning by performing a factory data reset.</string>
     <!-- Description of policy access to wipe the user's data -->
+    <string name="policydesc_wipeData" product="automotive">Erase the infotainment system\'s data without warning by performing a factory data reset.</string>
+    <!-- Description of policy access to wipe the user's data -->
     <string name="policydesc_wipeData" product="default">Erase the phone\'s data without warning by performing a factory data reset.</string>
     <!-- Title of policy access to wipe secondary user's data -->
-    <string name="policylab_wipeData_secondaryUser">Erase user data</string>
+    <string name="policylab_wipeData_secondaryUser" product="automotive">Erase profile data</string>
+    <!-- Title of policy access to wipe secondary user's data -->
+    <string name="policylab_wipeData_secondaryUser" product="default">Erase user data</string>
     <!-- Description of policy access to wipe the user's data -->
     <string name="policydesc_wipeData_secondaryUser" product="tablet">Erase this user\'s data on this tablet without warning.</string>
     <!-- Description of policy access to wipe the user's data -->
     <string name="policydesc_wipeData_secondaryUser" product="tv">Erase this user\'s data on this Android TV device without warning.</string>
     <!-- Description of policy access to wipe the user's data -->
+    <string name="policydesc_wipeData_secondaryUser" product="automotive">Erase this profile\'s data on this infotainment system without warning.</string>
+    <!-- Description of policy access to wipe the user's data -->
     <string name="policydesc_wipeData_secondaryUser" product="default">Erase this user\'s data on this phone without warning.</string>
     <!-- Title of policy access to set global proxy -->
     <string name="policylab_setGlobalProxy">Set the device global proxy</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 5208c4a..45d9a36 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1438,6 +1438,7 @@
   <java-symbol type="drawable" name="ic_qs_flashlight" />
   <java-symbol type="drawable" name="ic_qs_auto_rotate" />
   <java-symbol type="drawable" name="ic_qs_dnd" />
+  <java-symbol type="drawable" name="ic_qs_one_handed_mode" />
 
   <java-symbol type="drawable" name="sim_light_blue" />
   <java-symbol type="drawable" name="sim_light_green" />
@@ -1700,6 +1701,10 @@
   <java-symbol type="anim" name="activity_translucent_close_exit" />
   <java-symbol type="anim" name="activity_open_enter" />
   <java-symbol type="anim" name="activity_close_exit" />
+  <java-symbol type="anim" name="task_fragment_close_enter" />
+  <java-symbol type="anim" name="task_fragment_close_exit" />
+  <java-symbol type="anim" name="task_fragment_open_enter" />
+  <java-symbol type="anim" name="task_fragment_open_exit" />
 
   <java-symbol type="array" name="config_autoRotationTiltTolerance" />
   <java-symbol type="array" name="config_longPressVibePattern" />
@@ -1897,6 +1902,7 @@
   <java-symbol type="array" name="config_autoBrightnessLcdBacklightValues" />
   <java-symbol type="array" name="config_autoBrightnessLcdBacklightValues_doze" />
   <java-symbol type="array" name="config_autoBrightnessLevels" />
+  <java-symbol type="array" name="config_autoBrightnessLevelsIdle" />
   <java-symbol type="array" name="config_ambientThresholdLevels" />
   <java-symbol type="array" name="config_ambientBrighteningThresholds" />
   <java-symbol type="array" name="config_ambientDarkeningThresholds" />
@@ -2049,6 +2055,7 @@
   <java-symbol type="dimen" name="config_screenBrightnessSettingDefaultFloat" />
   <java-symbol type="dimen" name="config_screenBrightnessDozeFloat" />
   <java-symbol type="dimen" name="config_screenBrightnessDimFloat" />
+  <java-symbol type="dimen" name="config_screenBrightnessMinimumDimAmountFloat" />
   <java-symbol type="integer" name="config_screenBrightnessDark" />
   <java-symbol type="integer" name="config_screenBrightnessDim" />
   <java-symbol type="integer" name="config_screenBrightnessDoze" />
@@ -2231,6 +2238,7 @@
   <java-symbol type="string" name="config_primaryLocationTimeZoneProviderPackageName" />
   <java-symbol type="bool" name="config_enableSecondaryLocationTimeZoneProvider" />
   <java-symbol type="string" name="config_secondaryLocationTimeZoneProviderPackageName" />
+  <java-symbol type="bool" name="config_supportTelephonyTimeZoneFallback" />
   <java-symbol type="bool" name="config_autoResetAirplaneMode" />
   <java-symbol type="string" name="config_notificationAccessConfirmationActivity" />
   <java-symbol type="bool" name="config_killableInputMethods" />
@@ -3782,7 +3790,9 @@
   <java-symbol type="bool" name="config_fillMainBuiltInDisplayCutout" />
   <java-symbol type="drawable" name="ic_logout" />
 
+  <java-symbol type="bool" name="config_enableIdleScreenBrightnessMode" />
   <java-symbol type="array" name="config_autoBrightnessDisplayValuesNits" />
+  <java-symbol type="array" name="config_autoBrightnessDisplayValuesNitsIdle" />
   <java-symbol type="array" name="config_screenBrightnessBacklight" />
   <java-symbol type="array" name="config_screenBrightnessNits" />
 
@@ -3856,7 +3866,8 @@
 
   <!-- For Foldables -->
   <java-symbol type="array" name="config_foldedDeviceStates" />
-  <java-symbol type="integer" name="config_deviceStateOnWhichToWakeUp" />
+  <java-symbol type="array" name="config_deviceStatesOnWhichToWakeUp" />
+  <java-symbol type="array" name="config_deviceStatesOnWhichToSleep" />
   <java-symbol type="string" name="config_foldedArea" />
   <java-symbol type="bool" name="config_supportsConcurrentInternalDisplays" />
   <java-symbol type="bool" name="config_unfoldTransitionEnabled" />
@@ -4315,8 +4326,6 @@
 
   <java-symbol type="bool" name="config_voice_data_sms_auto_fallback" />
 
-  <java-symbol type="bool" name="config_enableDynamicKeyguardPositioning" />
-
   <java-symbol type="attr" name="colorAccentPrimary" />
   <java-symbol type="attr" name="colorAccentSecondary" />
   <java-symbol type="attr" name="colorAccentTertiary" />
@@ -4589,7 +4598,6 @@
   <java-symbol type="fraction" name="global_actions_vertical_padding_percentage" />
   <java-symbol type="fraction" name="global_actions_horizontal_padding_percentage" />
   <java-symbol type="drawable" name="global_actions_item_red_background" />
-  <java-symbol type="color" name="wear_material_grey_900" />
 
   <java-symbol type="string" name="config_wearSysUiPackage"/>
   <java-symbol type="string" name="config_wearSysUiMainActivity"/>
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
index 409025b..8eb6ebc 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
@@ -587,7 +587,8 @@
 
         final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
         mContext.registerReceiver(receiver, filter);
-        assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE));
+        assertEquals(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE),
+                BluetoothStatusCodes.SUCCESS);
         boolean success = false;
         try {
             success = completionSemaphore.tryAcquire(DISCOVERABLE_UNDISCOVERABLE_TIMEOUT,
@@ -637,7 +638,8 @@
 
         final IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
         mContext.registerReceiver(receiver, filter);
-        assertTrue(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE));
+        assertEquals(adapter.setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE),
+                BluetoothStatusCodes.SUCCESS);
         boolean success = false;
         try {
             success = completionSemaphore.tryAcquire(DISCOVERABLE_UNDISCOVERABLE_TIMEOUT,
diff --git a/core/tests/coretests/src/android/app/NotificationTest.java b/core/tests/coretests/src/android/app/NotificationTest.java
index 34c1763..37cf514 100644
--- a/core/tests/coretests/src/android/app/NotificationTest.java
+++ b/core/tests/coretests/src/android/app/NotificationTest.java
@@ -43,6 +43,7 @@
 import android.graphics.Color;
 import android.graphics.drawable.Icon;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.text.Spannable;
@@ -545,6 +546,29 @@
         validateColorizedPaletteForColor(Color.BLACK);
     }
 
+    @Test
+    public void testIsMediaNotification_nullSession_returnsFalse() {
+        // Null media session
+        Notification.MediaStyle mediaStyle = new Notification.MediaStyle();
+        Notification notification = new Notification.Builder(mContext, "test id")
+                .setStyle(mediaStyle)
+                .build();
+        assertFalse(notification.isMediaNotification());
+    }
+
+    @Test
+    public void testIsMediaNotification_invalidSession_returnsFalse() {
+        // Extra was set manually to an invalid type
+        Bundle extras = new Bundle();
+        extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, new Intent());
+        Notification.MediaStyle mediaStyle = new Notification.MediaStyle();
+        Notification notification = new Notification.Builder(mContext, "test id")
+                .setStyle(mediaStyle)
+                .addExtras(extras)
+                .build();
+        assertFalse(notification.isMediaNotification());
+    }
+
     public void validateColorizedPaletteForColor(int rawColor) {
         Notification.Colors cDay = new Notification.Colors();
         Notification.Colors cNight = new Notification.Colors();
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index 1f27063..5db6a3e 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -309,18 +309,22 @@
         final int numOfConfig = activity.mNumOfConfigChanges;
 
         final Configuration processConfigLandscape = new Configuration();
+        processConfigLandscape.orientation = ORIENTATION_LANDSCAPE;
         processConfigLandscape.windowConfiguration.setBounds(new Rect(0, 0, 100, 60));
         processConfigLandscape.seq = BASE_SEQ + 1;
 
         final Configuration activityConfigLandscape = new Configuration();
+        activityConfigLandscape.orientation = ORIENTATION_LANDSCAPE;
         activityConfigLandscape.windowConfiguration.setBounds(new Rect(0, 0, 100, 50));
         activityConfigLandscape.seq = BASE_SEQ + 2;
 
         final Configuration processConfigPortrait = new Configuration();
+        processConfigPortrait.orientation = ORIENTATION_PORTRAIT;
         processConfigPortrait.windowConfiguration.setBounds(new Rect(0, 0, 60, 100));
         processConfigPortrait.seq = BASE_SEQ + 3;
 
         final Configuration activityConfigPortrait = new Configuration();
+        activityConfigPortrait.orientation = ORIENTATION_PORTRAIT;
         activityConfigPortrait.windowConfiguration.setBounds(new Rect(0, 0, 50, 100));
         activityConfigPortrait.seq = BASE_SEQ + 4;
 
@@ -348,7 +352,8 @@
         assertEquals(activityConfigPortrait.windowConfiguration.getBounds(), bounds);
 
         // Ensure that Activity#onConfigurationChanged() not be called because the changes in
-        // WindowConfiguration shouldn't be reported.
+        // WindowConfiguration shouldn't be reported, and we only apply the latest Configuration
+        // update in transaction.
         assertEquals(numOfConfig, activity.mNumOfConfigChanges);
     }
 
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index df0c64c..207671e 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -453,7 +453,8 @@
                 boolean b2, boolean b3, Configuration configuration,
                 CompatibilityInfo compatibilityInfo, Map map, Bundle bundle1, String s1,
                 AutofillOptions ao, ContentCaptureOptions co, long[] disableCompatChanges,
-                SharedMemory serializedSystemFontMap)
+                SharedMemory serializedSystemFontMap,
+                long startRequestedElapsedTime, long startRequestedUptime)
                 throws RemoteException {
         }
 
diff --git a/core/tests/coretests/src/android/content/pm/PackagePartitionsTest.java b/core/tests/coretests/src/android/content/pm/PackagePartitionsTest.java
new file mode 100644
index 0000000..570b713
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/PackagePartitionsTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 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 android.content.pm;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static java.util.function.Function.identity;
+
+import android.content.pm.PackagePartitions.SystemPartition;
+import android.os.SystemProperties;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+public class PackagePartitionsTest {
+
+    @Test
+    public void testPackagePartitionsFingerprint() {
+        final ArrayList<SystemPartition> partitions = PackagePartitions.getOrderedPartitions(
+                identity());
+        final String[] properties = new String[partitions.size() + 1];
+        for (int i = 0; i < partitions.size(); i++) {
+            final String name = partitions.get(i).getName();
+            properties[i] = "ro." + name + ".build.fingerprint";
+        }
+        properties[partitions.size()] = "ro.build.fingerprint";
+
+        assertThat(SystemProperties.digestOf(properties)).isEqualTo(PackagePartitions.FINGERPRINT);
+    }
+}
diff --git a/core/tests/coretests/src/android/os/CombinedVibrationTest.java b/core/tests/coretests/src/android/os/CombinedVibrationTest.java
index 06b5d18..508856b 100644
--- a/core/tests/coretests/src/android/os/CombinedVibrationTest.java
+++ b/core/tests/coretests/src/android/os/CombinedVibrationTest.java
@@ -125,6 +125,12 @@
                 VibrationEffect.createOneShot(1, 1)).getDuration());
         assertEquals(-1, CombinedVibration.createParallel(
                 VibrationEffect.get(VibrationEffect.EFFECT_CLICK)).getDuration());
+        assertEquals(-1, CombinedVibration.createParallel(
+                        VibrationEffect.startComposition()
+                                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 100)
+                                .compose())
+                .getDuration());
         assertEquals(Long.MAX_VALUE, CombinedVibration.createParallel(
                 VibrationEffect.createWaveform(
                         new long[]{1, 2, 3}, new int[]{1, 2, 3}, 0)).getDuration());
@@ -175,6 +181,83 @@
     }
 
     @Test
+    public void testIsHapticFeedbackCandidateMono() {
+        assertTrue(CombinedVibration.createParallel(
+                VibrationEffect.createOneShot(1, 1)).isHapticFeedbackCandidate());
+        assertTrue(CombinedVibration.createParallel(
+                VibrationEffect.get(VibrationEffect.EFFECT_CLICK)).isHapticFeedbackCandidate());
+        assertTrue(CombinedVibration.createParallel(
+                        VibrationEffect.startComposition()
+                                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 100)
+                                .compose())
+                .isHapticFeedbackCandidate());
+        // Too long to be classified as a haptic feedback.
+        assertFalse(CombinedVibration.createParallel(
+                VibrationEffect.createOneShot(10_000, 1)).isHapticFeedbackCandidate());
+        // Repeating vibrations should not be classified as a haptic feedback.
+        assertFalse(CombinedVibration.createParallel(
+                VibrationEffect.createWaveform(new long[]{1}, new int[]{1}, 0))
+                .isHapticFeedbackCandidate());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidateStereo() {
+        assertTrue(CombinedVibration.startParallel()
+                .addVibrator(1, VibrationEffect.createOneShot(1, 1))
+                .addVibrator(2, VibrationEffect.createWaveform(new long[]{6}, new int[]{1}, -1))
+                .combine()
+                .isHapticFeedbackCandidate());
+        assertTrue(CombinedVibration.startParallel()
+                .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+                .addVibrator(2,
+                        VibrationEffect.startComposition()
+                                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 100)
+                                .compose())
+                .combine()
+                .isHapticFeedbackCandidate());
+        // Repeating vibrations should not be classified as a haptic feedback.
+        assertFalse(CombinedVibration.startParallel()
+                .addVibrator(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+                .addVibrator(2, VibrationEffect.createWaveform(new long[]{1}, new int[]{1}, 0))
+                .combine()
+                .isHapticFeedbackCandidate());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidateSequential() {
+        assertTrue(CombinedVibration.startSequential()
+                .addNext(1, VibrationEffect.createOneShot(10, 10), 10)
+                .addNext(2, VibrationEffect.createWaveform(new long[]{5}, new int[]{1}, -1))
+                .combine()
+                .isHapticFeedbackCandidate());
+        assertTrue(CombinedVibration.startSequential()
+                .addNext(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+                .addNext(2,
+                        VibrationEffect.startComposition()
+                                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SLOW_RISE)
+                                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL)
+                                .compose())
+                .combine()
+                .isHapticFeedbackCandidate());
+        // Repeating vibrations should not be classified as a haptic feedback.
+        assertFalse(CombinedVibration.startSequential()
+                .addNext(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+                .addNext(2, VibrationEffect.createWaveform(new long[]{1}, new int[]{1}, 0))
+                .combine()
+                .isHapticFeedbackCandidate());
+        // Too many effects to be classified as a haptic feedback.
+        assertFalse(CombinedVibration.startSequential()
+                .addNext(1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK))
+                .addNext(2, VibrationEffect.get(VibrationEffect.EFFECT_TICK))
+                .addNext(3, VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK))
+                .addNext(1, VibrationEffect.get(VibrationEffect.EFFECT_THUD))
+                .combine()
+                .isHapticFeedbackCandidate());
+    }
+
+    @Test
     public void testHasVibratorMono_returnsTrueForAnyVibrator() {
         CombinedVibration effect = CombinedVibration.createParallel(
                 VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
diff --git a/core/tests/coretests/src/android/os/VibrationEffectTest.java b/core/tests/coretests/src/android/os/VibrationEffectTest.java
index 6cbfffc..781564b 100644
--- a/core/tests/coretests/src/android/os/VibrationEffectTest.java
+++ b/core/tests/coretests/src/android/os/VibrationEffectTest.java
@@ -17,6 +17,7 @@
 package android.os;
 
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
@@ -312,8 +313,106 @@
         assertTrue(100 / 255f > ((StepSegment) scaledDown.getSegments().get(1)).getAmplitude());
     }
 
+
+    @Test
+    public void testDuration() {
+        assertEquals(1, VibrationEffect.createOneShot(1, 1).getDuration());
+        assertEquals(-1, VibrationEffect.get(VibrationEffect.EFFECT_CLICK).getDuration());
+        assertEquals(-1,
+                VibrationEffect.startComposition()
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1, 100)
+                        .compose()
+                        .getDuration());
+        assertEquals(6, VibrationEffect.createWaveform(
+                new long[]{1, 2, 3}, new int[]{1, 2, 3}, -1).getDuration());
+        assertEquals(Long.MAX_VALUE, VibrationEffect.createWaveform(
+                new long[]{1, 2, 3}, new int[]{1, 2, 3}, 0).getDuration());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_repeatingEffects_notCandidates() {
+        assertFalse(VibrationEffect.createWaveform(
+                new long[]{1, 2, 3}, new int[]{1, 2, 3}, 0).isHapticFeedbackCandidate());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_longEffects_notCandidates() {
+        assertFalse(VibrationEffect.createOneShot(1500, 255).isHapticFeedbackCandidate());
+        assertFalse(VibrationEffect.createWaveform(
+                new long[]{200, 200, 700}, new int[]{1, 2, 3}, -1).isHapticFeedbackCandidate());
+        assertFalse(VibrationEffect.startWaveform()
+                .addRamp(1, 500)
+                .addStep(1, 200)
+                .addRamp(0, 500)
+                .build()
+                .isHapticFeedbackCandidate());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_shortEffects_areCandidates() {
+        assertTrue(VibrationEffect.createOneShot(500, 255).isHapticFeedbackCandidate());
+        assertTrue(VibrationEffect.createWaveform(
+                new long[]{100, 200, 300}, new int[]{1, 2, 3}, -1).isHapticFeedbackCandidate());
+        assertTrue(VibrationEffect.startWaveform()
+                .addRamp(1, 300)
+                .addStep(1, 200)
+                .addRamp(0, 300)
+                .build()
+                .isHapticFeedbackCandidate());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_longCompositions_notCandidates() {
+        assertFalse(VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SPIN)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SLOW_RISE)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL)
+                .compose()
+                .isHapticFeedbackCandidate());
+
+        assertFalse(VibrationEffect.startComposition()
+                .addEffect(VibrationEffect.createOneShot(1500, 255))
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+                .compose()
+                .isHapticFeedbackCandidate());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_shortCompositions_areCandidates() {
+        assertTrue(VibrationEffect.startComposition()
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SLOW_RISE)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL)
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                .compose()
+                .isHapticFeedbackCandidate());
+
+        assertTrue(VibrationEffect.startComposition()
+                .addEffect(VibrationEffect.createOneShot(100, 255))
+                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+                .compose()
+                .isHapticFeedbackCandidate());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_prebakedRingtones_notCandidates() {
+        assertFalse(VibrationEffect.get(
+                VibrationEffect.RINGTONES[1]).isHapticFeedbackCandidate());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_prebakedNotRingtoneConstants_areCandidates() {
+        assertTrue(VibrationEffect.get(VibrationEffect.EFFECT_CLICK).isHapticFeedbackCandidate());
+        assertTrue(VibrationEffect.get(VibrationEffect.EFFECT_THUD).isHapticFeedbackCandidate());
+        assertTrue(VibrationEffect.get(VibrationEffect.EFFECT_TICK).isHapticFeedbackCandidate());
+    }
+
     private Resources mockRingtoneResources() {
-        return mockRingtoneResources(new String[] {
+        return mockRingtoneResources(new String[]{
                 RINGTONE_URI_1,
                 RINGTONE_URI_2,
                 RINGTONE_URI_3
diff --git a/core/tests/coretests/src/android/os/VibratorTest.java b/core/tests/coretests/src/android/os/VibratorTest.java
index 0ece793..bdd76a5 100644
--- a/core/tests/coretests/src/android/os/VibratorTest.java
+++ b/core/tests/coretests/src/android/os/VibratorTest.java
@@ -209,10 +209,21 @@
     }
 
     @Test
+    public void vibrate_withVibrationAttributes_usesGivenAttributes() {
+        VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
+        VibrationAttributes attributes = new VibrationAttributes.Builder().setUsage(
+                VibrationAttributes.USAGE_TOUCH).build();
+
+        mVibratorSpy.vibrate(effect, attributes);
+
+        verify(mVibratorSpy).vibrate(anyInt(), anyString(), eq(effect), isNull(), eq(attributes));
+    }
+
+    @Test
     public void vibrate_withAudioAttributes_createsVibrationAttributesWithSameUsage() {
         VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
         AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage(
-                AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY).build();
+                AudioAttributes.USAGE_VOICE_COMMUNICATION).build();
 
         mVibratorSpy.vibrate(effect, audioAttributes);
 
@@ -224,32 +235,12 @@
         assertEquals(VibrationAttributes.USAGE_COMMUNICATION_REQUEST,
                 vibrationAttributes.getUsage());
         // Keeps original AudioAttributes usage to be used by the VibratorService.
-        assertEquals(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY,
+        assertEquals(AudioAttributes.USAGE_VOICE_COMMUNICATION,
                 vibrationAttributes.getAudioUsage());
     }
 
     @Test
-    public void vibrate_withUnknownAudioAttributes_hasTouchUsageFromEffect() {
-        VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
-        AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage(
-                AudioAttributes.USAGE_UNKNOWN).build();
-
-        mVibratorSpy.vibrate(effect, audioAttributes);
-
-        ArgumentCaptor<VibrationAttributes> captor = ArgumentCaptor.forClass(
-                VibrationAttributes.class);
-        verify(mVibratorSpy).vibrate(anyInt(), anyString(), eq(effect), isNull(), captor.capture());
-
-        VibrationAttributes vibrationAttributes = captor.getValue();
-        assertEquals(VibrationAttributes.USAGE_TOUCH,
-                vibrationAttributes.getUsage());
-        // Sets AudioAttributes usage based on effect.
-        assertEquals(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION,
-                vibrationAttributes.getAudioUsage());
-    }
-
-    @Test
-    public void vibrate_withoutAudioAttributes_hasTouchUsageFromEffect() {
+    public void vibrate_withoutAudioAttributes_passesOnDefaultAttributes() {
         mVibratorSpy.vibrate(VibrationEffect.get(VibrationEffect.EFFECT_CLICK));
 
         ArgumentCaptor<VibrationAttributes> captor = ArgumentCaptor.forClass(
@@ -257,22 +248,6 @@
         verify(mVibratorSpy).vibrate(anyInt(), anyString(), any(), isNull(), captor.capture());
 
         VibrationAttributes vibrationAttributes = captor.getValue();
-        assertEquals(VibrationAttributes.USAGE_TOUCH, vibrationAttributes.getUsage());
-        // Sets AudioAttributes usage based on effect.
-        assertEquals(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION,
-                vibrationAttributes.getAudioUsage());
-    }
-
-    @Test
-    public void vibrate_withoutAudioAttributesAndLongEffect_hasUnknownUsage() {
-        mVibratorSpy.vibrate(VibrationEffect.createOneShot(10_000, 255));
-
-        ArgumentCaptor<VibrationAttributes> captor = ArgumentCaptor.forClass(
-                VibrationAttributes.class);
-        verify(mVibratorSpy).vibrate(anyInt(), anyString(), any(), isNull(), captor.capture());
-
-        VibrationAttributes vibrationAttributes = captor.getValue();
-        assertEquals(VibrationAttributes.USAGE_UNKNOWN, vibrationAttributes.getUsage());
-        assertEquals(AudioAttributes.USAGE_UNKNOWN, vibrationAttributes.getAudioUsage());
+        assertEquals(new VibrationAttributes.Builder().build(), vibrationAttributes);
     }
 }
diff --git a/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java
index de80812..a0e1f43 100644
--- a/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/PrebakedSegmentTest.java
@@ -17,6 +17,7 @@
 package android.os.vibrator;
 
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertSame;
 import static junit.framework.Assert.assertTrue;
 
@@ -105,4 +106,49 @@
                 VibrationEffect.EFFECT_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM);
         assertSame(prebaked, prebaked.scale(0.5f));
     }
+
+    @Test
+    public void testDuration() {
+        assertEquals(-1, new PrebakedSegment(
+                VibrationEffect.EFFECT_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+                .getDuration());
+        assertEquals(-1, new PrebakedSegment(
+                VibrationEffect.EFFECT_TICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+                .getDuration());
+        assertEquals(-1, new PrebakedSegment(
+                VibrationEffect.EFFECT_DOUBLE_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+                .getDuration());
+        assertEquals(-1, new PrebakedSegment(
+                VibrationEffect.EFFECT_THUD, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+                .getDuration());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_prebakedConstants_areCandidates() {
+        assertTrue(new PrebakedSegment(
+                VibrationEffect.EFFECT_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+                .isHapticFeedbackCandidate());
+        assertTrue(new PrebakedSegment(
+                VibrationEffect.EFFECT_TICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+                .isHapticFeedbackCandidate());
+        assertTrue(new PrebakedSegment(
+                VibrationEffect.EFFECT_DOUBLE_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+                .isHapticFeedbackCandidate());
+        assertTrue(new PrebakedSegment(
+                VibrationEffect.EFFECT_HEAVY_CLICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+                .isHapticFeedbackCandidate());
+        assertTrue(new PrebakedSegment(
+                VibrationEffect.EFFECT_THUD, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+                .isHapticFeedbackCandidate());
+        assertTrue(new PrebakedSegment(
+                VibrationEffect.EFFECT_TEXTURE_TICK, true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+                .isHapticFeedbackCandidate());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_prebakedRingtones_notCandidates() {
+        assertFalse(new PrebakedSegment(
+                VibrationEffect.RINGTONES[1], true, VibrationEffect.EFFECT_STRENGTH_MEDIUM)
+                .isHapticFeedbackCandidate());
+    }
 }
diff --git a/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java
index 538655b..a690553 100644
--- a/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/PrimitiveSegmentTest.java
@@ -127,4 +127,28 @@
         assertEquals(0f, initial.scale(1.5f).scale(2 / 3f).getScale(), TOLERANCE);
         assertEquals(0f, initial.scale(0.8f).scale(1.25f).getScale(), TOLERANCE);
     }
+
+    @Test
+    public void testDuration() {
+        assertEquals(-1, new PrimitiveSegment(
+                VibrationEffect.Composition.PRIMITIVE_NOOP, 1, 10).getDuration());
+        assertEquals(-1, new PrimitiveSegment(
+                VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 100).getDuration());
+        assertEquals(-1, new PrimitiveSegment(
+                VibrationEffect.Composition.PRIMITIVE_SPIN, 1, 0).getDuration());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_returnsTrue() {
+        assertTrue(new PrimitiveSegment(
+                VibrationEffect.Composition.PRIMITIVE_NOOP, 1, 10).isHapticFeedbackCandidate());
+        assertTrue(new PrimitiveSegment(
+                VibrationEffect.Composition.PRIMITIVE_CLICK, 1, 10).isHapticFeedbackCandidate());
+        assertTrue(new PrimitiveSegment(
+                VibrationEffect.Composition.PRIMITIVE_TICK, 1, 10).isHapticFeedbackCandidate());
+        assertTrue(new PrimitiveSegment(
+                VibrationEffect.Composition.PRIMITIVE_THUD, 1, 10).isHapticFeedbackCandidate());
+        assertTrue(new PrimitiveSegment(
+                VibrationEffect.Composition.PRIMITIVE_SPIN, 1, 10).isHapticFeedbackCandidate());
+    }
 }
diff --git a/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
index 174b4a7..5f80d2a 100644
--- a/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/RampSegmentTest.java
@@ -125,4 +125,16 @@
         assertEquals(0.35f, initial.scale(0.8f).getStartAmplitude(), TOLERANCE);
         assertEquals(0.5f, initial.scale(0.8f).scale(1.25f).getStartAmplitude(), TOLERANCE);
     }
+
+    @Test
+    public void testDuration() {
+        assertEquals(10, new RampSegment(0.5f, 1, 0, 0, 10).getDuration());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_returnsTrue() {
+        // A single ramp segment duration is not checked here, but contributes to the effect known
+        // duration checked in VibrationEffect implementations.
+        assertTrue(new RampSegment(0.5f, 1, 0, 0, 5_000).isHapticFeedbackCandidate());
+    }
 }
diff --git a/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java b/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
index 79529b8..fdce86a 100644
--- a/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
+++ b/core/tests/coretests/src/android/os/vibrator/StepSegmentTest.java
@@ -141,4 +141,16 @@
         assertEquals(VibrationEffect.DEFAULT_AMPLITUDE, initial.scale(1.5f).getAmplitude(),
                 TOLERANCE);
     }
+
+    @Test
+    public void testDuration() {
+        assertEquals(5, new StepSegment(0, 0, 5).getDuration());
+    }
+
+    @Test
+    public void testIsHapticFeedbackCandidate_returnsTrue() {
+        // A single step segment duration is not checked here, but contributes to the effect known
+        // duration checked in VibrationEffect implementations.
+        assertTrue(new StepSegment(0, 0, 5_000).isHapticFeedbackCandidate());
+    }
 }
diff --git a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
index 57bb434..d6a7682 100644
--- a/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
+++ b/core/tests/coretests/src/android/text/MeasuredParagraphTest.java
@@ -23,6 +23,7 @@
 
 import android.content.Context;
 import android.graphics.Typeface;
+import android.graphics.text.MeasuredText;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -135,7 +136,8 @@
         MeasuredParagraph mt = null;
 
         mt = MeasuredParagraph.buildForStaticLayout(
-                PAINT, "XXX", 0, 3, LTR, false, false, null /* no hint */, null);
+                PAINT, "XXX", 0, 3, LTR, MeasuredText.Builder.HYPHENATION_MODE_NONE, false,
+                null /* no hint */, null);
         assertNotNull(mt);
         assertNotNull(mt.getChars());
         assertEquals("XXX", charsToString(mt.getChars()));
@@ -150,7 +152,8 @@
 
         // Recycle it
         MeasuredParagraph mt2 = MeasuredParagraph.buildForStaticLayout(
-                PAINT, "_VVV_", 1, 4, RTL, false, false, null /* no hint */, mt);
+                PAINT, "_VVV_", 1, 4, RTL, MeasuredText.Builder.HYPHENATION_MODE_NONE, false,
+                null /* no hint */, mt);
         assertEquals(mt2, mt);
         assertNotNull(mt2.getChars());
         assertEquals("VVV", charsToString(mt.getChars()));
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 882a0da..e958a96 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -62,7 +62,7 @@
  * Tests for {@link ViewRootImpl}
  *
  * Build/Install/Run:
- * atest FrameworksCoreTests:ViewRootImplTest
+ *  atest FrameworksCoreTests:ViewRootImplTest
  */
 @Presubmit
 @SmallTest
@@ -300,7 +300,7 @@
     @Test
     public void whenWindowDoesNotHaveFocus_keysAreDropped() {
         checkKeyEvent(() -> {
-            mViewRootImpl.windowFocusChanged(false /*hasFocus*/, true /*inTouchMode*/);
+            mViewRootImpl.windowFocusChanged(false /*hasFocus*/);
         }, false /*shouldReceiveKey*/);
     }
 
@@ -310,7 +310,7 @@
     @Test
     public void whenWindowHasFocus_keysAreReceived() {
         checkKeyEvent(() -> {
-            mViewRootImpl.windowFocusChanged(true /*hasFocus*/, true /*inTouchMode*/);
+            mViewRootImpl.windowFocusChanged(true /*hasFocus*/);
         }, true /*shouldReceiveKey*/);
     }
 
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
index 0e78f87..e689b5d3 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
@@ -35,6 +35,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.os.SystemClock;
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.View;
@@ -44,7 +45,6 @@
 
 import com.google.common.base.Throwables;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -81,13 +81,6 @@
         mAccessibilityCache = new AccessibilityCache(mAccessibilityNodeRefresher);
     }
 
-    @After
-    public void tearDown() {
-        // Make sure we're recycling all of our window and node infos.
-        mAccessibilityCache.clear();
-        AccessibilityInteractionClient.getInstance().clearCache();
-    }
-
     @Test
     public void testEmptyCache_returnsNull() {
         assertNull(mAccessibilityCache.getNode(0, 0));
@@ -299,7 +292,8 @@
             SparseArray<List<AccessibilityWindowInfo>> allWindows = new SparseArray<>();
             allWindows.put(Display.DEFAULT_DISPLAY, windowsIn1);
             allWindows.put(SECONDARY_DISPLAY_ID, windowsIn2);
-            mAccessibilityCache.setWindowsOnAllDisplays(allWindows);
+            final long populationTimeStamp = SystemClock.uptimeMillis();
+            mAccessibilityCache.setWindowsOnAllDisplays(allWindows, populationTimeStamp);
             // Gets windows at default display.
             windowsOut1 = getWindowsByDisplay(Display.DEFAULT_DISPLAY);
             window1Out = mAccessibilityCache.getWindow(WINDOW_ID_1);
@@ -339,6 +333,46 @@
     }
 
     @Test
+    public void setInvalidWindowsAfterWindowsChangedEvent_notInCache() {
+        final AccessibilityEvent event = new AccessibilityEvent(
+                AccessibilityEvent.TYPE_WINDOWS_CHANGED);
+        final long eventTime = 1000L;
+        event.setEventTime(eventTime);
+        mAccessibilityCache.onAccessibilityEvent(event);
+
+        final AccessibilityWindowInfo windowInfo1 = obtainAccessibilityWindowInfo(WINDOW_ID_1,
+                SPECIFIC_WINDOW_LAYER);
+        List<AccessibilityWindowInfo> windowsIn = Arrays.asList(windowInfo1);
+        setWindowsByDisplay(Display.DEFAULT_DISPLAY, windowsIn, eventTime - 10);
+
+        try {
+            assertNull(getWindowsByDisplay(Display.DEFAULT_DISPLAY));
+        } finally {
+            windowInfo1.recycle();
+        }
+    }
+
+    @Test
+    public void setInvalidWindowsAfterStateChangedEvent_notInCache() {
+        final AccessibilityEvent event = new AccessibilityEvent(
+                AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+        final long eventTime = 1000L;
+        event.setEventTime(eventTime);
+        mAccessibilityCache.onAccessibilityEvent(event);
+
+        final AccessibilityWindowInfo windowInfo1 = obtainAccessibilityWindowInfo(WINDOW_ID_1,
+                SPECIFIC_WINDOW_LAYER);
+        List<AccessibilityWindowInfo> windowsIn = Arrays.asList(windowInfo1);
+        setWindowsByDisplay(Display.DEFAULT_DISPLAY, windowsIn, eventTime - 10);
+
+        try {
+            assertNull(getWindowsByDisplay(Display.DEFAULT_DISPLAY));
+        } finally {
+            windowInfo1.recycle();
+        }
+    }
+
+    @Test
     public void addWindowThenStateChangedEvent_noLongerInCache() {
         putWindowWithWindowIdAndDisplayIdInCache(WINDOW_ID_1, Display.DEFAULT_DISPLAY,
                 DEFAULT_WINDOW_LAYER);
@@ -1063,9 +1097,14 @@
     }
 
     private void setWindowsByDisplay(int displayId, List<AccessibilityWindowInfo> windows) {
+        setWindowsByDisplay(displayId, windows, SystemClock.uptimeMillis());
+    }
+
+    private void setWindowsByDisplay(int displayId, List<AccessibilityWindowInfo> windows,
+            long populationTimeStamp) {
         SparseArray<List<AccessibilityWindowInfo>> allWindows = new SparseArray<>();
         allWindows.put(displayId, windows);
-        mAccessibilityCache.setWindowsOnAllDisplays(allWindows);
+        mAccessibilityCache.setWindowsOnAllDisplays(allWindows, populationTimeStamp);
     }
 
     private List<AccessibilityWindowInfo> getWindowsByDisplay(int displayId) {
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
index 7e1e7f4..3e061d2 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityInteractionClientTest.java
@@ -17,6 +17,9 @@
 package android.view.accessibility;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.mockito.Mockito.verifyZeroInteractions;
 import static org.mockito.MockitoAnnotations.initMocks;
 
@@ -40,6 +43,8 @@
 @RunWith(AndroidJUnit4.class)
 public class AccessibilityInteractionClientTest {
     private static final int MOCK_CONNECTION_ID = 0xabcd;
+    private static final int MOCK_CONNECTION_OTHER_ID = 0xabce;
+
 
     private MockConnection mMockConnection = new MockConnection();
     @Mock private AccessibilityCache mMockCache;
@@ -47,8 +52,8 @@
     @Before
     public void setUp() {
         initMocks(this);
-        AccessibilityInteractionClient.setCache(mMockCache);
-        AccessibilityInteractionClient.addConnection(MOCK_CONNECTION_ID, mMockConnection);
+        AccessibilityInteractionClient.addConnection(
+                MOCK_CONNECTION_ID, mMockConnection, /*initializeCache=*/true);
     }
 
     /**
@@ -58,6 +63,7 @@
      */
     @Test
     public void findA11yNodeInfoByA11yId_whenBypassingCache_doesntTouchCache() {
+        AccessibilityInteractionClient.setCache(MOCK_CONNECTION_ID, mMockCache);
         final int windowId = 0x1234;
         final long accessibilityNodeId = 0x4321L;
         AccessibilityNodeInfo nodeFromConnection = AccessibilityNodeInfo.obtain();
@@ -71,6 +77,42 @@
         verifyZeroInteractions(mMockCache);
     }
 
+    @Test
+    public void getCache_differentConnections_returnsDifferentCaches() {
+        MockConnection mOtherMockConnection = new MockConnection();
+        AccessibilityInteractionClient.addConnection(
+                MOCK_CONNECTION_OTHER_ID, mOtherMockConnection, /*initializeCache=*/true);
+
+        AccessibilityCache firstCache = AccessibilityInteractionClient.getCache(MOCK_CONNECTION_ID);
+        AccessibilityCache secondCache = AccessibilityInteractionClient.getCache(
+                MOCK_CONNECTION_OTHER_ID);
+        assertNotEquals(firstCache, secondCache);
+    }
+
+    @Test
+    public void getCache_addConnectionWithoutCache_returnsNullCache() {
+        // Need to first remove from process cache
+        AccessibilityInteractionClient.removeConnection(MOCK_CONNECTION_OTHER_ID);
+
+        MockConnection mOtherMockConnection = new MockConnection();
+        AccessibilityInteractionClient.addConnection(
+                MOCK_CONNECTION_OTHER_ID, mOtherMockConnection, /*initializeCache=*/false);
+
+        AccessibilityCache cache = AccessibilityInteractionClient.getCache(
+                MOCK_CONNECTION_OTHER_ID);
+        assertNull(cache);
+    }
+
+    @Test
+    public void getCache_removeConnection_returnsNull() {
+        AccessibilityCache cache = AccessibilityInteractionClient.getCache(MOCK_CONNECTION_ID);
+        assertNotNull(cache);
+
+        AccessibilityInteractionClient.removeConnection(MOCK_CONNECTION_ID);
+        cache = AccessibilityInteractionClient.getCache(MOCK_CONNECTION_ID);
+        assertNull(cache);
+    }
+
     private static class MockConnection extends AccessibilityServiceConnectionImpl {
         AccessibilityNodeInfo mInfoToReturn;
 
diff --git a/core/tests/coretests/src/android/window/WindowContextControllerTest.java b/core/tests/coretests/src/android/window/WindowContextControllerTest.java
index a6e351d..52cb9f3 100644
--- a/core/tests/coretests/src/android/window/WindowContextControllerTest.java
+++ b/core/tests/coretests/src/android/window/WindowContextControllerTest.java
@@ -24,16 +24,13 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
-import android.content.res.Configuration;
 import android.os.Binder;
 import android.platform.test.annotations.Presubmit;
-import android.view.IWindowManager;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -59,17 +56,14 @@
 public class WindowContextControllerTest {
     private WindowContextController mController;
     @Mock
-    private IWindowManager mMockWms;
-    @Mock
     private WindowTokenClient mMockToken;
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
-        mController = new WindowContextController(mMockToken, mMockWms);
+        mController = new WindowContextController(mMockToken);
         doNothing().when(mMockToken).onConfigurationChanged(any(), anyInt(), anyBoolean());
-        doReturn(new Configuration()).when(mMockWms).attachWindowContextToDisplayArea(any(),
-                anyInt(), anyInt(), any());
+        doReturn(true).when(mMockToken).attachToDisplayArea(anyInt(), anyInt(), any());
     }
 
     @Test(expected = IllegalStateException.class)
@@ -81,10 +75,10 @@
     }
 
     @Test
-    public void testDetachIfNeeded_NotAttachedYet_DoNothing() throws Exception {
+    public void testDetachIfNeeded_NotAttachedYet_DoNothing() {
         mController.detachIfNeeded();
 
-        verify(mMockWms, never()).detachWindowContextFromWindowContainer(any());
+        verify(mMockToken, never()).detachFromWindowContainerIfNeeded();
     }
 
     @Test
@@ -93,8 +87,6 @@
                 null /* options */);
 
         assertThat(mController.mAttachedToDisplayArea).isTrue();
-        verify(mMockToken).onConfigurationChanged(any(), eq(DEFAULT_DISPLAY),
-                eq(false) /* shouldReportConfigChange */);
 
         mController.detachIfNeeded();
 
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
index 8b060ff..8ec33bf 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsImplTest.java
@@ -16,7 +16,6 @@
 
 package com.android.internal.os;
 
-import static android.os.BatteryStats.STATS_SINCE_CHARGED;
 import static android.os.BatteryStats.Uid.NUM_PROCESS_STATE;
 import static android.os.BatteryStats.Uid.PROCESS_STATE_BACKGROUND;
 import static android.os.BatteryStats.Uid.PROCESS_STATE_CACHED;
@@ -25,8 +24,10 @@
 
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
@@ -115,14 +116,17 @@
                 {989834, 384098, 98483, 23809, 4984},
                 {4859048, 348903, 4578967, 5973894, 298549}
         };
+
+        final long[] timeInFreqs = new long[NUM_CPU_FREQS];
+
         for (int i = 0; i < testUids.length; ++i) {
             mockKernelSingleUidTimeReader(testUids[i], cpuTimes[i]);
 
             // Verify there are no cpu times initially.
             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStatsLocked(testUids[i]);
             for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
-                assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
-                assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
+                assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
             }
         }
         addPendingUids(testUids, testProcStates);
@@ -134,13 +138,13 @@
         for (int i = 0; i < testUids.length; ++i) {
             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
             for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
+                final boolean hasTimeInFreq = u.getCpuFreqTimes(timeInFreqs, procState);
                 if (procState == testProcStates[i]) {
-                    assertArrayEquals("Uid=" + testUids[i], cpuTimes[i],
-                            u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                    assertArrayEquals("Uid=" + testUids[i], cpuTimes[i], timeInFreqs);
                 } else {
-                    assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                    assertFalse(hasTimeInFreq);
                 }
-                assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
             }
         }
 
@@ -172,12 +176,12 @@
                     for (int j = 0; j < expectedCpuTimes.length; ++j) {
                         expectedCpuTimes[j] += delta1[i][j];
                     }
-                    assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes,
-                            u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                    assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
+                    assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
                 } else {
-                    assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                    assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
                 }
-                assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
             }
         }
 
@@ -214,13 +218,13 @@
                     for (int j = 0; j < expectedCpuTimes.length; ++j) {
                         expectedCpuTimes[j] += delta1[i][j] + delta2[i][j];
                     }
-                    assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes,
-                            u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
-                    assertArrayEquals("Uid=" + testUids[i], delta2[i],
-                            u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                    assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
+                    assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
+                    assertTrue(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
+                    assertArrayEquals("Uid=" + testUids[i], delta2[i], timeInFreqs);
                 } else {
-                    assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
-                    assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                    assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
+                    assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
                 }
             }
         }
@@ -262,18 +266,18 @@
                         expectedCpuTimes[j] += delta1[i][j] + delta2[i][j] + delta3[i][j]
                                 + (testUids[i] == parentUid ? isolatedUidCpuTimes[j] : 0);
                     }
-                    assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes,
-                            u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                    assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
+                    assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes, timeInFreqs);
                     long[] expectedScreenOffTimes = delta2[i].clone();
                     for (int j = 0; j < expectedScreenOffTimes.length; ++j) {
                         expectedScreenOffTimes[j] += delta3[i][j]
                                 + (testUids[i] == parentUid ? isolatedUidCpuTimes[j] : 0);
                     }
-                    assertArrayEquals("Uid=" + testUids[i], expectedScreenOffTimes,
-                            u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                    assertTrue(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
+                    assertArrayEquals("Uid=" + testUids[i], expectedScreenOffTimes, timeInFreqs);
                 } else {
-                    assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
-                    assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                    assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
+                    assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
                 }
             }
         }
@@ -329,16 +333,19 @@
         mBatteryStatsImpl.copyFromAllUidsCpuTimes(true, false);
 
         verifyNoPendingUids();
+
+        final long[] timeInFreqs = new long[NUM_CPU_FREQS];
+
         for (int i = 0; i < testUids.length; ++i) {
             final BatteryStats.Uid u = mBatteryStatsImpl.getUidStats().get(testUids[i]);
             for (int procState = 0; procState < NUM_PROCESS_STATE; ++procState) {
                 if (procState == testProcStates[i]) {
-                    assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes[i],
-                            u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                    assertTrue(u.getCpuFreqTimes(timeInFreqs, procState));
+                    assertArrayEquals("Uid=" + testUids[i], expectedCpuTimes[i], timeInFreqs);
                 } else {
-                    assertNull(u.getCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                    assertFalse(u.getCpuFreqTimes(timeInFreqs, procState));
                 }
-                assertNull(u.getScreenOffCpuFreqTimes(STATS_SINCE_CHARGED, procState));
+                assertFalse(u.getScreenOffCpuFreqTimes(timeInFreqs, procState));
             }
         }
     }
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
index 055fc71..db63e6e 100644
--- a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
@@ -160,6 +160,34 @@
         verify(callback).onStateChanged(eq(mService.getBaseState()));
     }
 
+    @Test
+    public void verifyDeviceStateRequestCallbacksCalled() {
+        DeviceStateRequest.Callback callback = mock(TestDeviceStateRequestCallback.class);
+
+        DeviceStateRequest request = DeviceStateRequest.newBuilder(OTHER_DEVICE_STATE).build();
+        mDeviceStateManagerGlobal.requestState(request,
+                ConcurrentUtils.DIRECT_EXECUTOR /* executor */,
+                callback /* callback */);
+
+        verify(callback).onRequestActivated(eq(request));
+        Mockito.reset(callback);
+
+        mDeviceStateManagerGlobal.cancelRequest(request);
+
+        verify(callback).onRequestCanceled(eq(request));
+    }
+
+    public static class TestDeviceStateRequestCallback implements DeviceStateRequest.Callback {
+        @Override
+        public void onRequestActivated(DeviceStateRequest request) { }
+
+        @Override
+        public void onRequestCanceled(DeviceStateRequest request) { }
+
+        @Override
+        public void onRequestSuspended(DeviceStateRequest request) { }
+    }
+
     private static final class TestDeviceStateManagerService extends IDeviceStateManager.Stub {
         public static final class Request {
             public final IBinder token;
diff --git a/data/etc/Android.bp b/data/etc/Android.bp
index be1e2b2..88228f2 100644
--- a/data/etc/Android.bp
+++ b/data/etc/Android.bp
@@ -12,7 +12,6 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-
 // Sysconfig files
 
 package {
@@ -119,6 +118,13 @@
 }
 
 prebuilt_etc {
+    name: "privapp_whitelist_com.android.intentresolver",
+    sub_dir: "permissions",
+    src: "com.android.intentresolver.xml",
+    filename_from_src: true,
+}
+
+prebuilt_etc {
     name: "privapp_whitelist_com.android.launcher3",
     system_ext_specific: true,
     sub_dir: "permissions",
diff --git a/packages/SystemUI/res/color/prv_text_color_on_accent.xml b/data/etc/com.android.intentresolver.xml
similarity index 63%
copy from packages/SystemUI/res/color/prv_text_color_on_accent.xml
copy to data/etc/com.android.intentresolver.xml
index 9f44aca..f4e94ad 100644
--- a/packages/SystemUI/res/color/prv_text_color_on_accent.xml
+++ b/data/etc/com.android.intentresolver.xml
@@ -12,9 +12,12 @@
   ~ 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
   -->
-<selector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-          xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="?androidprv:attr/textColorOnAccent" />
-</selector>
\ No newline at end of file
+<permissions>
+    <privapp-permissions package="com.android.intentresolver">
+        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+        <permission name="android.permission.MANAGE_USERS"/>
+        <permission name="android.permission.PACKAGE_USAGE_STATS"/>
+    </privapp-permissions>
+</permissions>
diff --git a/packages/overlays/OneHandedModeGesturalOverlay/Android.bp b/data/etc/displayconfig/Android.bp
similarity index 77%
rename from packages/overlays/OneHandedModeGesturalOverlay/Android.bp
rename to data/etc/displayconfig/Android.bp
index 468069d..b2a45d2 100644
--- a/packages/overlays/OneHandedModeGesturalOverlay/Android.bp
+++ b/data/etc/displayconfig/Android.bp
@@ -1,18 +1,16 @@
+// Copyright 2021 The Android Open Source Project
 //
-//  Copyright 2020, The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
+// 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
+//      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 {
     // See: http://go/android-license-faq
@@ -23,8 +21,8 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
-runtime_resource_overlay {
-    name: "OneHandedModeGesturalOverlay",
-    theme: "OneHandedModeGestural",
-    product_specific: true,
+prebuilt_etc {
+    name: "default_television.xml",
+    sub_dir: "displayconfig",
+    src: "default_television.xml",
 }
diff --git a/data/etc/displayconfig/OWNERS b/data/etc/displayconfig/OWNERS
new file mode 100644
index 0000000..6ce1ee4
--- /dev/null
+++ b/data/etc/displayconfig/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/display/OWNERS
diff --git a/data/etc/displayconfig/default_television.xml b/data/etc/displayconfig/default_television.xml
new file mode 100644
index 0000000..2540f59
--- /dev/null
+++ b/data/etc/displayconfig/default_television.xml
@@ -0,0 +1,24 @@
+<displayConfiguration>
+    <densityMap>
+         <density>
+            <height>480</height>
+            <width>720</width>
+            <density>120</density>
+         </density>
+         <density>
+            <height>720</height>
+            <width>1280</width>
+            <density>213</density>
+         </density>
+         <density>
+            <height>1080</height>
+            <width>1920</width>
+            <density>320</density>
+         </density>
+         <density>
+            <height>2160</height>
+            <width>3840</width>
+            <density>640</density>
+         </density>
+    </densityMap>
+</displayConfiguration>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 6983aa4..f83f401 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -225,6 +225,8 @@
         <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
         <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
         <permission name="android.permission.USE_RESERVED_DISK"/>
+        <permission name="android.permission.READ_COMPAT_CHANGE_CONFIG" />
+        <permission name="android.permission.LOG_COMPAT_CHANGE" />
     </privapp-permissions>
 
     <privapp-permissions package="com.android.providers.downloads">
@@ -420,6 +422,11 @@
         <permission name="android.permission.MANAGE_NOTIFICATIONS"/>
         <!-- Permission required for CompanionDeviceManager CTS test. -->
         <permission name="android.permission.COMPANION_APPROVE_WIFI_CONNECTIONS" />
+        <permission name="android.permission.MANAGE_COMPANION_DEVICES" />
+        <permission name="android.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING" />
+        <permission name="android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION" />
+        <permission name="android.permission.REQUEST_COMPANION_PROFILE_WATCH" />
+        <permission name="android.permission.REQUEST_COMPANION_SELF_MANAGED" />
         <!-- Permission required for testing registering pull atom callbacks. -->
         <permission name="android.permission.REGISTER_STATS_PULL_ATOM"/>
         <!-- Permission required for testing system audio effect APIs. -->
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 8b37805..6bfbd8d 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -889,6 +889,12 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/NonAppWindowAnimationAdapter.java"
     },
+    "-1145384901": {
+      "message": "shouldWaitAnimatingExit: isTransition: %s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/WindowState.java"
+    },
     "-1142279614": {
       "message": "Looking for focus: %s, flags=%d, canReceive=%b, reason=%s",
       "level": "VERBOSE",
@@ -961,6 +967,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/RootWindowContainer.java"
     },
+    "-1101551167": {
+      "message": "Auto-PIP allowed, entering PIP mode directly: %s, didAutoPip: %b",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_STATES",
+      "at": "com\/android\/server\/wm\/TaskFragment.java"
+    },
     "-1089874824": {
       "message": "SURFACE SHOW (performLayout): %s",
       "level": "INFO",
@@ -1267,6 +1279,12 @@
       "group": "WM_DEBUG_SCREEN_ON",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-743856570": {
+      "message": "shouldWaitAnimatingExit: isAnimating: %s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/WindowState.java"
+    },
     "-743431900": {
       "message": "Configuration no differences in %s",
       "level": "VERBOSE",
@@ -1771,6 +1789,12 @@
       "group": "WM_DEBUG_SYNC_ENGINE",
       "at": "com\/android\/server\/wm\/BLASTSyncEngine.java"
     },
+    "-208825711": {
+      "message": "shouldWaitAnimatingExit: isWallpaperTarget: %s",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/WindowState.java"
+    },
     "-198463978": {
       "message": "updateRotationUnchecked: alwaysSendConfiguration=%b forceRelayout=%b",
       "level": "VERBOSE",
@@ -2629,12 +2653,6 @@
       "group": "WM_ERROR",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
-    "660908897": {
-      "message": "Auto-PIP allowed, entering PIP mode directly: %s",
-      "level": "DEBUG",
-      "group": "WM_DEBUG_STATES",
-      "at": "com\/android\/server\/wm\/TaskFragment.java"
-    },
     "662572728": {
       "message": "Attempted to add a toast window with bad token %s.  Aborting.",
       "level": "WARN",
@@ -2989,6 +3007,12 @@
       "group": "WM_DEBUG_REMOTE_ANIMATIONS",
       "at": "com\/android\/server\/wm\/WallpaperAnimationAdapter.java"
     },
+    "1087494661": {
+      "message": "Clear window stuck on animatingExit status: %s",
+      "level": "WARN",
+      "group": "WM_DEBUG_APP_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/WindowState.java"
+    },
     "1088929964": {
       "message": "onLockTaskPackagesUpdated: starting new locktask task=%s",
       "level": "DEBUG",
diff --git a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
index 0f356a6..2f56b18 100644
--- a/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
+++ b/graphics/java/android/graphics/drawable/AdaptiveIconDrawable.java
@@ -74,6 +74,10 @@
  *      getBounds().right + getBounds().getWidth() * #getExtraInsetFraction(),
  *      getBounds().bottom + getBounds().getHeight() * #getExtraInsetFraction())
  * </pre>
+ *
+ * <p>An alternate drawable can be specified using <code>&lt;monochrome></code> tag which can be
+ * drawn in place of the two (background and foreground) layers. This drawable is tinted
+ * according to the device or surface theme.
  */
 public class AdaptiveIconDrawable extends Drawable implements Drawable.Callback {
 
@@ -120,6 +124,7 @@
      */
     private static final int BACKGROUND_ID = 0;
     private static final int FOREGROUND_ID = 1;
+    private static final int MONOCHROME_ID = 2;
 
     /**
      * State variable that maintains the {@link ChildDrawable} array.
@@ -188,6 +193,18 @@
      */
     public AdaptiveIconDrawable(Drawable backgroundDrawable,
             Drawable foregroundDrawable) {
+        this(backgroundDrawable, foregroundDrawable, null);
+    }
+
+    /**
+     * Constructor used to dynamically create this drawable.
+     *
+     * @param backgroundDrawable drawable that should be rendered in the background
+     * @param foregroundDrawable drawable that should be rendered in the foreground
+     * @param monochromeDrawable an alternate drawable which can be tinted per system theme color
+     */
+    public AdaptiveIconDrawable(@Nullable Drawable backgroundDrawable,
+            @Nullable Drawable foregroundDrawable, @Nullable Drawable monochromeDrawable) {
         this((LayerState)null, null);
         if (backgroundDrawable != null) {
             addLayer(BACKGROUND_ID, createChildDrawable(backgroundDrawable));
@@ -195,6 +212,9 @@
         if (foregroundDrawable != null) {
             addLayer(FOREGROUND_ID, createChildDrawable(foregroundDrawable));
         }
+        if (monochromeDrawable != null) {
+            addLayer(MONOCHROME_ID, createChildDrawable(monochromeDrawable));
+        }
     }
 
     /**
@@ -227,9 +247,8 @@
         state.mSourceDrawableId = Resources.getAttributeSetSourceResId(attrs);
 
         final ChildDrawable[] array = state.mChildren;
-        for (int i = 0; i < state.mChildren.length; i++) {
-            final ChildDrawable layer = array[i];
-            layer.setDensity(deviceDensity);
+        for (int i = 0; i < array.length; i++) {
+            array[i].setDensity(deviceDensity);
         }
 
         inflateLayers(r, parser, attrs, theme);
@@ -286,6 +305,18 @@
         return mLayerState.mChildren[BACKGROUND_ID].mDrawable;
     }
 
+
+    /**
+     * Returns the monochrome version of this drawable. Callers can use a tinted version of
+     * this drawable instead of the original drawable on surfaces stressing user theming.
+     *
+     *  @return the monochrome drawable
+     */
+    @Nullable
+    public Drawable getMonochrome() {
+        return mLayerState.mChildren[MONOCHROME_ID].mDrawable;
+    }
+
     @Override
     protected void onBoundsChange(Rect bounds) {
         if (bounds.isEmpty()) {
@@ -316,9 +347,6 @@
 
         for (int i = 0, count = mLayerState.N_CHILDREN; i < count; i++) {
             final ChildDrawable r = mLayerState.mChildren[i];
-            if (r == null) {
-                continue;
-            }
             final Drawable d = r.mDrawable;
             if (d == null) {
                 continue;
@@ -359,14 +387,11 @@
         if (mLayersShader == null) {
             mCanvas.setBitmap(mLayersBitmap);
             mCanvas.drawColor(Color.BLACK);
-            for (int i = 0; i < mLayerState.N_CHILDREN; i++) {
-                if (mLayerState.mChildren[i] == null) {
-                    continue;
-                }
-                final Drawable dr = mLayerState.mChildren[i].mDrawable;
-                if (dr != null) {
-                    dr.draw(mCanvas);
-                }
+            if (mLayerState.mChildren[BACKGROUND_ID].mDrawable != null) {
+                mLayerState.mChildren[BACKGROUND_ID].mDrawable.draw(mCanvas);
+            }
+            if (mLayerState.mChildren[FOREGROUND_ID].mDrawable != null) {
+                mLayerState.mChildren[FOREGROUND_ID].mDrawable.draw(mCanvas);
             }
             mLayersShader = new BitmapShader(mLayersBitmap, TileMode.CLAMP, TileMode.CLAMP);
             mPaint.setShader(mLayersShader);
@@ -480,12 +505,18 @@
                 continue;
             }
             String tagName = parser.getName();
-            if (tagName.equals("background")) {
-                childIndex = BACKGROUND_ID;
-            } else if (tagName.equals("foreground")) {
-                childIndex = FOREGROUND_ID;
-            } else {
-                continue;
+            switch (tagName) {
+                case "background":
+                    childIndex = BACKGROUND_ID;
+                    break;
+                case "foreground":
+                    childIndex = FOREGROUND_ID;
+                    break;
+                case "monochrome":
+                    childIndex = MONOCHROME_ID;
+                    break;
+                default:
+                    continue;
             }
 
             final ChildDrawable layer = new ChildDrawable(state.mDensity);
@@ -941,7 +972,7 @@
     static class LayerState extends ConstantState {
         private int[] mThemeAttrs;
 
-        final static int N_CHILDREN = 2;
+        static final int N_CHILDREN = 3;
         ChildDrawable[] mChildren;
 
         // The density at which to render the drawable and its children.
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 7354c90..b843589 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -79,7 +79,7 @@
  * mask using {@code setId(..., android.R.id.mask)} or an existing mask layer
  * may be replaced using {@code setDrawableByLayerId(android.R.id.mask, ...)}.
  * <pre>
- * <code>&lt;!-- A red ripple masked against an opaque rectangle. --/>
+ * <code>&lt;!-- A red ripple masked against an opaque rectangle. -->
  * &lt;ripple android:color="#ffff0000">
  *   &lt;item android:id="@android:id/mask"
  *         android:drawable="@android:color/white" />
@@ -92,12 +92,12 @@
  * If no mask layer is set, the ripple effect is masked against the composite
  * of the child layers.
  * <pre>
- * <code>&lt;!-- A green ripple drawn atop a black rectangle. --/>
+ * <code>&lt;!-- A green ripple drawn atop a black rectangle. -->
  * &lt;ripple android:color="#ff00ff00">
  *   &lt;item android:drawable="@android:color/black" />
  * &lt;/ripple>
  *
- * &lt;!-- A blue ripple drawn atop a drawable resource. --/>
+ * &lt;!-- A blue ripple drawn atop a drawable resource. -->
  * &lt;ripple android:color="#ff0000ff">
  *   &lt;item android:drawable="@drawable/my_drawable" />
  * &lt;/ripple></code>
@@ -108,7 +108,7 @@
  * background within the View's hierarchy. In this case, the drawing region
  * may extend outside of the Drawable bounds.
  * <pre>
- * <code>&lt;!-- An unbounded red ripple. --/>
+ * <code>&lt;!-- An unbounded red ripple. -->
  * &lt;ripple android:color="#ffff0000" /></code>
  * </pre>
  *
diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java
index 31c3d09..a34d0ab 100644
--- a/graphics/java/android/graphics/text/MeasuredText.java
+++ b/graphics/java/android/graphics/text/MeasuredText.java
@@ -17,12 +17,14 @@
 package android.graphics.text;
 
 import android.annotation.FloatRange;
+import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.Px;
 import android.graphics.Paint;
 import android.graphics.Rect;
+import android.util.Log;
 
 import com.android.internal.util.Preconditions;
 
@@ -30,6 +32,9 @@
 
 import libcore.util.NativeAllocationRegistry;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * Result of text shaping of the single paragraph string.
  *
@@ -49,6 +54,8 @@
  * </p>
  */
 public class MeasuredText {
+    private static final String TAG = "MeasuredText";
+
     private long mNativePtr;
     private boolean mComputeHyphenation;
     private boolean mComputeLayout;
@@ -179,6 +186,7 @@
         private final @NonNull char[] mText;
         private boolean mComputeHyphenation = false;
         private boolean mComputeLayout = true;
+        private boolean mFastHyphenation = false;
         private int mCurrentOffset = 0;
         private @Nullable MeasuredText mHintMt = null;
 
@@ -275,10 +283,76 @@
          * Even if you pass false to this method, you can still enable automatic hyphenation of
          * LineBreaker but line break computation becomes slower.
          *
+         * @deprecated use setComputeHyphenation(int) instead.
+         *
          * @param computeHyphenation true if you want to use automatic hyphenations.
          */
-        public @NonNull Builder setComputeHyphenation(boolean computeHyphenation) {
-            mComputeHyphenation = computeHyphenation;
+        public @NonNull @Deprecated Builder setComputeHyphenation(boolean computeHyphenation) {
+            setComputeHyphenation(
+                    computeHyphenation ? HYPHENATION_MODE_NORMAL : HYPHENATION_MODE_NONE);
+            return this;
+        }
+
+        /** @hide */
+        @IntDef(prefix = { "HYPHENATION_MODE_" }, value = {
+                HYPHENATION_MODE_NONE,
+                HYPHENATION_MODE_NORMAL,
+                HYPHENATION_MODE_FAST
+        })
+        @Retention(RetentionPolicy.SOURCE)
+        public @interface HyphenationMode {}
+
+        /**
+         * A value for hyphenation calculation mode.
+         *
+         * This value indicates that no hyphenation points are calculated.
+         */
+        public static final int HYPHENATION_MODE_NONE = 0;
+
+        /**
+         * A value for hyphenation calculation mode.
+         *
+         * This value indicates that hyphenation points are calculated.
+         */
+        public static final int HYPHENATION_MODE_NORMAL = 1;
+
+        /**
+         * A value for hyphenation calculation mode.
+         *
+         * This value indicates that hyphenation points are calculated with faster algorithm. This
+         * algorithm measures text width with ignoring the context of hyphen character shaping, e.g.
+         * kerning.
+         */
+        public static final int HYPHENATION_MODE_FAST = 2;
+
+        /**
+         * By passing true to this method, the build method will calculate hyphenation break
+         * points faster with ignoring some typographic features, e.g. kerning.
+         *
+         * {@link #HYPHENATION_MODE_NONE} is by default.
+         *
+         * @param mode a hyphenation mode.
+         */
+        public @NonNull Builder setComputeHyphenation(@HyphenationMode int mode) {
+            switch (mode) {
+                case HYPHENATION_MODE_NONE:
+                    mComputeHyphenation = false;
+                    mFastHyphenation = false;
+                    break;
+                case HYPHENATION_MODE_NORMAL:
+                    mComputeHyphenation = true;
+                    mFastHyphenation = false;
+                    break;
+                case HYPHENATION_MODE_FAST:
+                    mComputeHyphenation = true;
+                    mFastHyphenation = true;
+                    break;
+                default:
+                    Log.e(TAG, "Unknown hyphenation mode: " + mode);
+                    mComputeHyphenation = false;
+                    mFastHyphenation = false;
+                    break;
+            }
             return this;
         }
 
@@ -319,7 +393,7 @@
             try {
                 long hintPtr = (mHintMt == null) ? 0 : mHintMt.getNativePtr();
                 long ptr = nBuildMeasuredText(mNativePtr, hintPtr, mText, mComputeHyphenation,
-                        mComputeLayout);
+                        mComputeLayout, mFastHyphenation);
                 final MeasuredText res = new MeasuredText(ptr, mText, mComputeHyphenation,
                         mComputeLayout);
                 sRegistry.registerNativeAllocation(res, ptr);
@@ -378,7 +452,8 @@
                 long hintMtPtr,
                 @NonNull char[] text,
                 boolean computeHyphenation,
-                boolean computeLayout);
+                boolean computeLayout,
+                boolean fastHyphenationMode);
 
         private static native void nFreeBuilder(/* Non Zero */ long nativeBuilderPtr);
     }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
index 85ef270..df751fc 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -27,8 +27,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.util.ArrayMap;
-import android.view.SurfaceControl;
-import android.window.TaskFragmentAppearedInfo;
 import android.window.TaskFragmentCreationParams;
 import android.window.TaskFragmentInfo;
 import android.window.TaskFragmentOrganizer;
@@ -51,9 +49,6 @@
     /** Mapping from the client assigned unique token to the {@link TaskFragmentInfo}. */
     private final Map<IBinder, TaskFragmentInfo> mFragmentInfos = new ArrayMap<>();
 
-    /** Mapping from the client assigned unique token to the TaskFragment {@link SurfaceControl}. */
-    private final Map<IBinder, SurfaceControl> mFragmentLeashes = new ArrayMap<>();
-
     /**
      * Mapping from the client assigned unique token to the TaskFragment parent
      * {@link Configuration}.
@@ -67,7 +62,7 @@
      * Callback that notifies the controller about changes to task fragments.
      */
     interface TaskFragmentCallback {
-        void onTaskFragmentAppeared(@NonNull TaskFragmentAppearedInfo taskFragmentAppearedInfo);
+        void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo);
         void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo);
         void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo);
         void onTaskFragmentParentInfoChanged(@NonNull IBinder fragmentToken,
@@ -259,15 +254,12 @@
     }
 
     @Override
-    public void onTaskFragmentAppeared(@NonNull TaskFragmentAppearedInfo taskFragmentAppearedInfo) {
-        final TaskFragmentInfo info = taskFragmentAppearedInfo.getTaskFragmentInfo();
-        final IBinder fragmentToken = info.getFragmentToken();
-        final SurfaceControl leash = taskFragmentAppearedInfo.getLeash();
-        mFragmentInfos.put(fragmentToken, info);
-        mFragmentLeashes.put(fragmentToken, leash);
+    public void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo) {
+        final IBinder fragmentToken = taskFragmentInfo.getFragmentToken();
+        mFragmentInfos.put(fragmentToken, taskFragmentInfo);
 
         if (mCallback != null) {
-            mCallback.onTaskFragmentAppeared(taskFragmentAppearedInfo);
+            mCallback.onTaskFragmentAppeared(taskFragmentInfo);
         }
     }
 
@@ -284,7 +276,6 @@
     @Override
     public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {
         mFragmentInfos.remove(taskFragmentInfo.getFragmentToken());
-        mFragmentLeashes.remove(taskFragmentInfo.getFragmentToken());
         mFragmentParentConfigs.remove(taskFragmentInfo.getFragmentToken());
 
         if (mCallback != null) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
index 68c1904..fe6c7ba 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -37,7 +37,6 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
-import android.window.TaskFragmentAppearedInfo;
 import android.window.TaskFragmentInfo;
 import android.window.WindowContainerTransaction;
 
@@ -110,14 +109,13 @@
     }
 
     @Override
-    public void onTaskFragmentAppeared(@NonNull TaskFragmentAppearedInfo taskFragmentAppearedInfo) {
-        TaskFragmentContainer container = getContainer(
-                taskFragmentAppearedInfo.getTaskFragmentInfo().getFragmentToken());
+    public void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo) {
+        TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
         if (container == null) {
             return;
         }
 
-        container.setInfo(taskFragmentAppearedInfo.getTaskFragmentInfo());
+        container.setInfo(taskFragmentInfo);
         if (container.isFinished()) {
             mPresenter.cleanupContainer(container, false /* shouldFinishDependent */);
         }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java
index 194b633..89d7a40 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java
@@ -39,6 +39,8 @@
 
     final Transformation mTransformation = new Transformation();
     final float[] mMatrix = new float[9];
+    final float[] mVecs = new float[4];
+    final Rect mRect = new Rect();
     private boolean mIsFirstFrame = true;
 
     TaskFragmentAnimationAdapter(@NonNull Animation animation,
@@ -76,6 +78,22 @@
                 mTarget.localBounds.left, mTarget.localBounds.top);
         t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix);
         t.setAlpha(mLeash, mTransformation.getAlpha());
+
+        // Open/close animation may scale up the surface. Apply an inverse scale to the window crop
+        // so that it will not be covering other windows.
+        mVecs[1] = mVecs[2] = 0;
+        mVecs[0] = mVecs[3] = 1;
+        mTransformation.getMatrix().mapVectors(mVecs);
+        mVecs[0] = 1.f / mVecs[0];
+        mVecs[3] = 1.f / mVecs[3];
+        final Rect clipRect = mTarget.localBounds;
+        mRect.left = (int) (clipRect.left * mVecs[0] + 0.5f);
+        mRect.right = (int) (clipRect.right * mVecs[0] + 0.5f);
+        mRect.top = (int) (clipRect.top * mVecs[3] + 0.5f);
+        mRect.bottom = (int) (clipRect.bottom * mVecs[3] + 0.5f);
+        mRect.offsetTo(Math.round(mTarget.localBounds.width() * (1 - mVecs[0]) / 2.f),
+                Math.round(mTarget.localBounds.height() * (1 - mVecs[3]) / 2.f));
+        t.setWindowCrop(mLeash, mRect);
     }
 
     /** Called after animation finished. */
@@ -157,8 +175,6 @@
      * Should be used for the animation of the {@link RemoteAnimationTarget} that has size change.
      */
     static class BoundsChangeAdapter extends TaskFragmentAnimationAdapter {
-        private final float[] mVecs = new float[4];
-        private final Rect mRect = new Rect();
 
         BoundsChangeAdapter(@NonNull Animation animation, @NonNull RemoteAnimationTarget target) {
             super(animation, target);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java
index 535dac1..3c7d2de 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationController.java
@@ -16,9 +16,13 @@
 
 package androidx.window.extensions.embedding;
 
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
 import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE;
 import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
 import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
 
 import android.util.Log;
 import android.view.RemoteAnimationAdapter;
@@ -45,8 +49,12 @@
         final RemoteAnimationDefinition definition = new RemoteAnimationDefinition();
         final RemoteAnimationAdapter animationAdapter =
                 new RemoteAnimationAdapter(mRemoteRunner, 0, 0, true /* changeNeedsSnapshot */);
+        definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_OPEN, animationAdapter);
         definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_OPEN, animationAdapter);
+        definition.addRemoteAnimation(TRANSIT_OLD_TASK_OPEN, animationAdapter);
+        definition.addRemoteAnimation(TRANSIT_OLD_ACTIVITY_CLOSE, animationAdapter);
         definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CLOSE, animationAdapter);
+        definition.addRemoteAnimation(TRANSIT_OLD_TASK_CLOSE, animationAdapter);
         definition.addRemoteAnimation(TRANSIT_OLD_TASK_FRAGMENT_CHANGE, animationAdapter);
         mOrganizer.registerRemoteAnimations(definition);
     }
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
index 412559e..8c8ef92 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java
@@ -17,9 +17,13 @@
 package androidx.window.extensions.embedding;
 
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE;
+import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
 import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE;
 import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE;
 import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN;
+import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
 
 import android.animation.Animator;
 import android.animation.ValueAnimator;
@@ -155,9 +159,13 @@
             @WindowManager.TransitionOldType int transit,
             @NonNull RemoteAnimationTarget[] targets) {
         switch (transit) {
+            case TRANSIT_OLD_ACTIVITY_OPEN:
             case TRANSIT_OLD_TASK_FRAGMENT_OPEN:
+            case TRANSIT_OLD_TASK_OPEN:
                 return createOpenAnimationAdapters(targets);
+            case TRANSIT_OLD_ACTIVITY_CLOSE:
             case TRANSIT_OLD_TASK_FRAGMENT_CLOSE:
+            case TRANSIT_OLD_TASK_CLOSE:
                 return createCloseAnimationAdapters(targets);
             case TRANSIT_OLD_TASK_FRAGMENT_CHANGE:
                 return createChangeAnimationAdapters(targets);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
index c0908a5..586ac1f 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java
@@ -43,6 +43,7 @@
 import com.android.internal.policy.TransitionAnimation;
 
 /** Animation spec for TaskFragment transition. */
+// TODO(b/206557124): provide an easier way to customize animation
 class TaskFragmentAnimationSpec {
 
     private static final String TAG = "TaskFragAnimationSpec";
@@ -179,9 +180,9 @@
     Animation loadOpenAnimation(@NonNull RemoteAnimationTarget target,
             @NonNull Rect wholeAnimationBounds) {
         final boolean isEnter = target.mode != MODE_CLOSING;
-        final Animation animation = mTransitionAnimation.loadDefaultAnimationAttr(isEnter
-                ? R.styleable.WindowAnimation_activityOpenEnterAnimation
-                : R.styleable.WindowAnimation_activityOpenExitAnimation);
+        final Animation animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
+                ? com.android.internal.R.anim.task_fragment_open_enter
+                : com.android.internal.R.anim.task_fragment_open_exit);
         animation.initialize(target.localBounds.width(), target.localBounds.height(),
                 wholeAnimationBounds.width(), wholeAnimationBounds.height());
         animation.scaleCurrentDuration(mTransitionAnimationScaleSetting);
@@ -191,9 +192,9 @@
     Animation loadCloseAnimation(@NonNull RemoteAnimationTarget target,
             @NonNull Rect wholeAnimationBounds) {
         final boolean isEnter = target.mode != MODE_CLOSING;
-        final Animation animation = mTransitionAnimation.loadDefaultAnimationAttr(isEnter
-                ? R.styleable.WindowAnimation_activityCloseEnterAnimation
-                : R.styleable.WindowAnimation_activityCloseExitAnimation);
+        final Animation animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter
+                ? com.android.internal.R.anim.task_fragment_close_enter
+                : com.android.internal.R.anim.task_fragment_close_exit);
         animation.initialize(target.localBounds.width(), target.localBounds.height(),
                 wholeAnimationBounds.width(), wholeAnimationBounds.height());
         animation.scaleCurrentDuration(mTransitionAnimationScaleSetting);
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
index 32d447e..fe9ce97 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java
@@ -18,9 +18,12 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static androidx.window.common.DisplayFeature.COMMON_STATE_FLAT;
+import static androidx.window.common.DisplayFeature.COMMON_STATE_HALF_OPENED;
 import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation;
 import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect;
 
+import android.annotation.Nullable;
 import android.app.Activity;
 import android.content.Context;
 import android.graphics.Rect;
@@ -119,22 +122,45 @@
         return !mWindowLayoutChangeListeners.isEmpty();
     }
 
-    private int getFeatureState(DisplayFeature feature) {
+    /**
+     * Calculate the {@link DisplayFeature.State} from the feature or the device posture producer.
+     * If the given {@link DisplayFeature.State} is not valid then {@code null} will be returned.
+     * The {@link FoldingFeature} should be ignored in the case of an invalid
+     * {@link DisplayFeature.State}.
+     *
+     * @param feature a {@link DisplayFeature} to provide the feature state if present.
+     * @return {@link DisplayFeature.State} of the hinge if present or the state from the posture
+     * produce if present.
+     */
+    @Nullable
+    private Integer getFeatureState(DisplayFeature feature) {
         Integer featureState = feature.getState();
         Optional<Integer> posture = mDevicePostureProducer.getData();
-        int fallbackPosture = posture.orElse(DisplayFeature.COMMON_STATE_FLAT);
-        int displayFeatureState = featureState == null ? fallbackPosture : featureState;
-        return convertToExtensionState(displayFeatureState);
+        Integer state = featureState == null ? posture.orElse(null) : featureState;
+        return convertToExtensionState(state);
     }
 
-    private int convertToExtensionState(int state) {
-        switch (state) {
-            case DisplayFeature.COMMON_STATE_FLAT:
-                return FoldingFeature.STATE_FLAT;
-            case DisplayFeature.COMMON_STATE_HALF_OPENED:
-                return FoldingFeature.STATE_HALF_OPENED;
+    /**
+     * A convenience method to translate from the common feature state to the extensions feature
+     * state.  More specifically, translates from {@link DisplayFeature.State} to
+     * {@link FoldingFeature.STATE_FLAT} or {@link FoldingFeature.STATE_HALF_OPENED}. If it is not
+     * possible to translate, then we will return a {@code null} value.
+     *
+     * @param state if it matches a value in {@link DisplayFeature.State}, {@code null} otherwise.
+     * @return a {@link FoldingFeature.STATE_FLAT} or {@link FoldingFeature.STATE_HALF_OPENED} if
+     * the given state matches a value in {@link DisplayFeature.State} and {@code null} otherwise.
+     */
+    @Nullable
+    private Integer convertToExtensionState(@Nullable Integer state) {
+        if (state == null) { // The null check avoids a NullPointerException.
+            return null;
+        } else if (state == COMMON_STATE_FLAT) {
+            return FoldingFeature.STATE_FLAT;
+        } else if (state == COMMON_STATE_HALF_OPENED) {
+            return FoldingFeature.STATE_HALF_OPENED;
+        } else {
+            return null;
         }
-        return FoldingFeature.STATE_FLAT;
     }
 
     private void onDisplayFeaturesChanged() {
@@ -151,6 +177,25 @@
         return new WindowLayoutInfo(displayFeatures);
     }
 
+    /**
+     * Translate from the {@link DisplayFeature} to
+     * {@link androidx.window.extensions.layout.DisplayFeature} for a given {@link Activity}. If a
+     * {@link DisplayFeature} is not valid then it will be omitted.
+     *
+     * For a {@link FoldingFeature} the bounds are localized into the {@link Activity} window
+     * coordinate space and the state is calculated either from {@link DisplayFeature#getState()} or
+     * {@link #mDisplayFeatureProducer}. The state from {@link #mDisplayFeatureProducer} may not be
+     * valid since {@link #mDisplayFeatureProducer} is a general state controller. If the state is
+     * not valid, the {@link FoldingFeature} is omitted from the {@link List} of
+     * {@link androidx.window.extensions.layout.DisplayFeature}. If the bounds are not valid,
+     * constructing a {@link FoldingFeature} will throw an {@link IllegalArgumentException} since
+     * this can cause negative UI effects down stream.
+     *
+     * @param activity a proxy for the {@link android.view.Window} that contains the
+     * {@link androidx.window.extensions.layout.DisplayFeature}.
+     * @return a {@link List} of valid {@link androidx.window.extensions.layout.DisplayFeature} that
+     * are within the {@link android.view.Window} of the {@link Activity}
+     */
     private List<androidx.window.extensions.layout.DisplayFeature> getDisplayFeatures(
             @NonNull Activity activity) {
         List<androidx.window.extensions.layout.DisplayFeature> features = new ArrayList<>();
@@ -170,6 +215,10 @@
         if (storedFeatures.isPresent()) {
 
             for (DisplayFeature baseFeature : storedFeatures.get()) {
+                Integer state = getFeatureState(baseFeature);
+                if (state == null) {
+                    continue;
+                }
                 Rect featureRect = baseFeature.getRect();
                 rotateRectToDisplayRotation(displayId, featureRect);
                 transformToWindowSpaceRect(activity, featureRect);
diff --git a/packages/SystemUI/res/color/prv_text_color_on_accent.xml b/libs/WindowManager/Shell/res/color/size_compat_background_ripple.xml
similarity index 76%
rename from packages/SystemUI/res/color/prv_text_color_on_accent.xml
rename to libs/WindowManager/Shell/res/color/size_compat_background_ripple.xml
index 9f44aca..329e5b9 100644
--- a/packages/SystemUI/res/color/prv_text_color_on_accent.xml
+++ b/libs/WindowManager/Shell/res/color/size_compat_background_ripple.xml
@@ -14,7 +14,6 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<selector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-          xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="?androidprv:attr/textColorOnAccent" />
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:color="@android:color/system_neutral1_500" android:lStar="35" />
 </selector>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/size_compat_hint_bubble.xml b/libs/WindowManager/Shell/res/drawable/size_compat_hint_bubble.xml
index 94165a1..22cd384 100644
--- a/libs/WindowManager/Shell/res/drawable/size_compat_hint_bubble.xml
+++ b/libs/WindowManager/Shell/res/drawable/size_compat_hint_bubble.xml
@@ -16,6 +16,6 @@
   -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
        android:shape="rectangle">
-    <solid android:color="@color/size_compat_hint_bubble"/>
+    <solid android:color="@color/size_compat_background"/>
     <corners android:radius="@dimen/size_compat_hint_corner_radius"/>
 </shape>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/size_compat_hint_point.xml b/libs/WindowManager/Shell/res/drawable/size_compat_hint_point.xml
index a8f0f76..af9063a 100644
--- a/libs/WindowManager/Shell/res/drawable/size_compat_hint_point.xml
+++ b/libs/WindowManager/Shell/res/drawable/size_compat_hint_point.xml
@@ -20,6 +20,6 @@
         android:viewportWidth="10"
         android:viewportHeight="8">
     <path
-        android:fillColor="@color/size_compat_hint_bubble"
+        android:fillColor="@color/size_compat_background"
         android:pathData="M10,0 l-4.1875,6.6875 a1,1 0 0,1 -1.625,0 l-4.1875,-6.6875z"/>
 </vector>
diff --git a/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml
index 3e486df..18caa35 100644
--- a/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml
+++ b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button.xml
@@ -20,16 +20,16 @@
         android:viewportWidth="48"
         android:viewportHeight="48">
     <path
-        android:fillColor="#53534D"
+        android:fillColor="@color/size_compat_background"
         android:pathData="M0,24 a24,24 0 1,0 48,0 a24,24 0 1,0 -48,0" />
     <group
         android:translateX="12"
         android:translateY="12">
         <path
-            android:fillColor="#E4E3DA"
+            android:fillColor="@color/size_compat_text"
             android:pathData="M6,13c0,-1.65 0.67,-3.15 1.76,-4.24L6.34,7.34C4.9,8.79 4,10.79 4,13c0,4.08 3.05,7.44 7,7.93v-2.02C8.17,18.43 6,15.97 6,13z"/>
         <path
-            android:fillColor="#E4E3DA"
+            android:fillColor="@color/size_compat_text"
             android:pathData="M20,13c0,-4.42 -3.58,-8 -8,-8c-0.06,0 -0.12,0.01 -0.18,0.01v0l1.09,-1.09L11.5,2.5L8,6l3.5,3.5l1.41,-1.41l-1.08,-1.08C11.89,7.01 11.95,7 12,7c3.31,0 6,2.69 6,6c0,2.97 -2.17,5.43 -5,5.91v2.02C16.95,20.44 20,17.08 20,13z"/>
     </group>
 </vector>
diff --git a/packages/SystemUI/res/color/prv_text_color_on_accent.xml b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button_ripple.xml
similarity index 74%
copy from packages/SystemUI/res/color/prv_text_color_on_accent.xml
copy to libs/WindowManager/Shell/res/drawable/size_compat_restart_button_ripple.xml
index 9f44aca..95decff 100644
--- a/packages/SystemUI/res/color/prv_text_color_on_accent.xml
+++ b/libs/WindowManager/Shell/res/drawable/size_compat_restart_button_ripple.xml
@@ -14,7 +14,7 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<selector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-          xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="?androidprv:attr/textColorOnAccent" />
-</selector>
\ No newline at end of file
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/size_compat_background_ripple">
+    <item android:drawable="@drawable/size_compat_restart_button"/>
+</ripple>
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml b/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml
index 17347f6..d0e7c42 100644
--- a/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml
+++ b/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml
@@ -40,7 +40,7 @@
                 android:padding="16dp"
                 android:text="@string/restart_button_description"
                 android:textAlignment="viewStart"
-                android:textColor="#E4E3DA"
+                android:textColor="@color/size_compat_text"
                 android:textSize="14sp"/>
 
             <ImageView
diff --git a/libs/WindowManager/Shell/res/layout/size_compat_ui.xml b/libs/WindowManager/Shell/res/layout/size_compat_ui.xml
index 47e76f0..82ebee2 100644
--- a/libs/WindowManager/Shell/res/layout/size_compat_ui.xml
+++ b/libs/WindowManager/Shell/res/layout/size_compat_ui.xml
@@ -30,7 +30,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center"
-            android:src="@drawable/size_compat_restart_button"
+            android:src="@drawable/size_compat_restart_button_ripple"
             android:background="@android:color/transparent"
             android:contentDescription="@string/restart_button_description"/>
 
diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml
index 69aa31e..107da81 100644
--- a/libs/WindowManager/Shell/res/values-af/strings.xml
+++ b/libs/WindowManager/Shell/res/values-af/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Maak toe"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Vou uit"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Instellings"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Gaan by verdeelde skerm in"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Kieslys"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in beeld-in-beeld"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"As jy nie wil hê dat <xliff:g id="NAME">%s</xliff:g> hierdie kenmerk moet gebruik nie, tik om instellings oop te maak en skakel dit af."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Bestuur"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Borrel is toegemaak."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Tik om hierdie program te herbegin en maak volskerm oop."</string>
-    <string name="got_it" msgid="4428750913636945527">"Het dit"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml
index c754e3ca..d724372 100644
--- a/libs/WindowManager/Shell/res/values-am/strings.xml
+++ b/libs/WindowManager/Shell/res/values-am/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"ዝጋ"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"ዘርጋ"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"ቅንብሮች"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"የተከፈለ ማያ ገጽን አስገባ"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"ምናሌ"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> በስዕል-ላይ-ስዕል ውስጥ ነው"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ይህን ባህሪ እንዲጠቀም ካልፈለጉ ቅንብሮችን ለመክፈት መታ ያድርጉና ያጥፉት።"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ያቀናብሩ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"አረፋ ተሰናብቷል።"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"ይህን መተግበሪያ ዳግም ለማስነሳት መታ ያድርጉ እና ወደ ሙሉ ማያ ገጽ ይሂዱ።"</string>
-    <string name="got_it" msgid="4428750913636945527">"ገባኝ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml
index ac72a3d..7dd1f81 100644
--- a/libs/WindowManager/Shell/res/values-ar/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ar/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"إغلاق"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"توسيع"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"الإعدادات"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"الدخول في وضع تقسيم الشاشة"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"القائمة"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> يظهر في صورة داخل صورة"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"إذا كنت لا تريد أن يستخدم <xliff:g id="NAME">%s</xliff:g> هذه الميزة، فانقر لفتح الإعدادات، ثم أوقِف تفعيل هذه الميزة."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"إدارة"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"تم إغلاق الفقاعة."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"انقر لإعادة تشغيل هذا التطبيق والانتقال إلى وضع ملء الشاشة."</string>
-    <string name="got_it" msgid="4428750913636945527">"حسنًا"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml
index 3258385..190f7ca 100644
--- a/libs/WindowManager/Shell/res/values-as/strings.xml
+++ b/libs/WindowManager/Shell/res/values-as/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"বন্ধ কৰক"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"বিস্তাৰ কৰক"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"ছেটিং"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"বিভাজিত স্ক্ৰীন ম’ডলৈ যাওক"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"মেনু"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> চিত্ৰৰ ভিতৰৰ চিত্ৰত আছে"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"আপুনি যদি <xliff:g id="NAME">%s</xliff:g> সুবিধাটো ব্যৱহাৰ কৰিব নোখোজে, তেন্তে ছেটিং খুলিবলৈ টিপক আৰু তালৈ গৈ ইয়াক অফ কৰক।"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"পৰিচালনা কৰক"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"বাবল অগ্ৰাহ্য কৰা হৈছে"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"এপ্‌টো ৰিষ্টাৰ্ট কৰিবলৈ আৰু পূৰ্ণ স্ক্ৰীন ব্যৱহাৰ কৰিবলৈ টিপক।"</string>
-    <string name="got_it" msgid="4428750913636945527">"বুজি পালোঁ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml
index 6d3e0a9..e33a35f 100644
--- a/libs/WindowManager/Shell/res/values-az/strings.xml
+++ b/libs/WindowManager/Shell/res/values-az/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Bağlayın"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Genişləndirin"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Ayarlar"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Bölünmüş ekrana daxil olun"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menyu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> şəkil içində şəkildədir"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> tətbiqinin bu funksiyadan istifadə etməyini istəmirsinizsə, ayarları açmaq və deaktiv etmək üçün klikləyin."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"İdarə edin"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Qabarcıqdan imtina edilib."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Bu tətbiqi sıfırlayaraq tam ekrana keçmək üçün toxunun."</string>
-    <string name="got_it" msgid="4428750913636945527">"Anladım"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
index 358da25..f59e932 100644
--- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Zatvori"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Proširi"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Podešavanja"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Uđi na podeljeni ekran"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Meni"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je slika u slici"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da biste otvorili podešavanja i isključili je."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljajte"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblačić je odbačen."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Dodirnite da biste restartovali aplikaciju i prešli u režim celog ekrana."</string>
-    <string name="got_it" msgid="4428750913636945527">"Važi"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml
index 7a934cc..3b478f2 100644
--- a/libs/WindowManager/Shell/res/values-be/strings.xml
+++ b/libs/WindowManager/Shell/res/values-be/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Закрыць"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Разгарнуць"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Налады"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Падзяліць экран"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> з’яўляецца відарысам у відарысе"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Калі вы не хочаце, каб праграма <xliff:g id="NAME">%s</xliff:g> выкарыстоўвала гэту функцыю, дакраніцеся, каб адкрыць налады і адключыць яе."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Кіраваць"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Усплывальнае апавяшчэнне адхілена."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Націсніце, каб перазапусціць гэту праграму і перайсці ў поўнаэкранны рэжым."</string>
-    <string name="got_it" msgid="4428750913636945527">"Зразумела"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml
index 02930b1..3a77a1c 100644
--- a/libs/WindowManager/Shell/res/values-bg/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bg/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Затваряне"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Разгъване"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Настройки"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Преминаване към разделен екран"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> е в режима „Картина в картината“"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ако не искате <xliff:g id="NAME">%s</xliff:g> да използва тази функция, докоснете, за да отворите настройките, и я изключете."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Управление"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Балончето е отхвърлено."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Докоснете, за да рестартирате това приложение в режим на цял екран."</string>
-    <string name="got_it" msgid="4428750913636945527">"Разбрах"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml
index b35e179..8bfd775 100644
--- a/libs/WindowManager/Shell/res/values-bn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bn/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"বন্ধ করুন"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"বড় করুন"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"সেটিংস"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"\'স্প্লিট স্ক্রিন\' মোড চালু করুন"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"মেনু"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"ছবির-মধ্যে-ছবি তে <xliff:g id="NAME">%s</xliff:g> আছেন"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> কে এই বৈশিষ্ট্যটি ব্যবহার করতে দিতে না চাইলে ট্যাপ করে সেটিংসে গিয়ে সেটি বন্ধ করে দিন।"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ম্যানেজ করুন"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"বাবল বাতিল করা হয়েছে।"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"এই অ্যাপ রিস্টার্ট করতে ট্যাপ করুন ও \'ফুল-স্ক্রিন\' মোড ব্যবহার করুন।"</string>
-    <string name="got_it" msgid="4428750913636945527">"বুঝেছি"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml
index 14d90a4..d23cc61 100644
--- a/libs/WindowManager/Shell/res/values-bs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-bs/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Zatvori"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Proširi"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Postavke"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Otvori podijeljeni ekran"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Meni"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je u načinu priakza Slika u slici"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da otvorite postavke i isključite je."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljaj"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblačić je odbačen."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Dodirnite da ponovo pokrenete ovu aplikaciju i aktivirate prikaz preko cijelog ekrana."</string>
-    <string name="got_it" msgid="4428750913636945527">"Razumijem"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml
index 9cffbdd..6434e31 100644
--- a/libs/WindowManager/Shell/res/values-ca/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ca/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Tanca"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Desplega"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Configuració"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Entra al mode de pantalla dividida"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> està en pantalla en pantalla"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Si no vols que <xliff:g id="NAME">%s</xliff:g> utilitzi aquesta funció, toca per obrir la configuració i desactiva-la."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestiona"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"La bombolla s\'ha ignorat."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Toca per reiniciar aquesta aplicació i passar a pantalla completa."</string>
-    <string name="got_it" msgid="4428750913636945527">"Entesos"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml
index 9b5206a..3530a7c 100644
--- a/libs/WindowManager/Shell/res/values-cs/strings.xml
+++ b/libs/WindowManager/Shell/res/values-cs/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Zavřít"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Rozbalit"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Nastavení"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Aktivovat rozdělenou obrazovku"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Nabídka"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"Aplikace <xliff:g id="NAME">%s</xliff:g> je v režimu obraz v obraze"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Pokud nechcete, aby aplikace <xliff:g id="NAME">%s</xliff:g> tuto funkci používala, klepnutím otevřete nastavení a funkci vypněte."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Spravovat"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bublina byla zavřena."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Klepnutím aplikaci restartujete a přejdete na režim celé obrazovky"</string>
-    <string name="got_it" msgid="4428750913636945527">"Rozumím"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml
index a06abf1..89b66e5 100644
--- a/libs/WindowManager/Shell/res/values-da/strings.xml
+++ b/libs/WindowManager/Shell/res/values-da/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Luk"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Udvid"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Indstillinger"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Åbn opdelt skærm"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> vises som integreret billede"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Hvis du ikke ønsker, at <xliff:g id="NAME">%s</xliff:g> skal benytte denne funktion, kan du åbne indstillingerne og deaktivere den."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Administrer"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Boblen blev lukket."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Tryk for at genstarte denne app, og gå til fuld skærm."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml
index c5e79f8..b49b446 100644
--- a/libs/WindowManager/Shell/res/values-de/strings.xml
+++ b/libs/WindowManager/Shell/res/values-de/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Schließen"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Maximieren"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Einstellungen"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"„Bildschirm teilen“ aktivieren"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ist in Bild im Bild"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Wenn du nicht möchtest, dass <xliff:g id="NAME">%s</xliff:g> diese Funktion verwendet, tippe, um die Einstellungen zu öffnen und die Funktion zu deaktivieren."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Verwalten"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble verworfen."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Tippe, um die App im Vollbildmodus neu zu starten."</string>
-    <string name="got_it" msgid="4428750913636945527">"Ok"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml
index fc397c5..ed1d913 100644
--- a/libs/WindowManager/Shell/res/values-el/strings.xml
+++ b/libs/WindowManager/Shell/res/values-el/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Κλείσιμο"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Ανάπτυξη"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Ρυθμίσεις"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Μετάβαση σε διαχωρισμό οθόνης"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Μενού"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"Η λειτουργία picture-in-picture είναι ενεργή σε <xliff:g id="NAME">%s</xliff:g>."</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Εάν δεν θέλετε να χρησιμοποιείται αυτή η λειτουργία από την εφαρμογή <xliff:g id="NAME">%s</xliff:g>, πατήστε για να ανοίξετε τις ρυθμίσεις και απενεργοποιήστε την."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Διαχείριση"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Το συννεφάκι παραβλέφθηκε."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Πατήστε για επανεκκίνηση αυτής της εφαρμογής και ενεργοποίηση πλήρους οθόνης."</string>
-    <string name="got_it" msgid="4428750913636945527">"Το κατάλαβα"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
index a4f287f..067e998 100644
--- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Close"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Expand"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Tap to restart this app and go full screen."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
index a4f287f..067e998 100644
--- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Close"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Expand"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Tap to restart this app and go full screen."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
index a4f287f..067e998 100644
--- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Close"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Expand"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Tap to restart this app and go full screen."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
index a4f287f..067e998 100644
--- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Close"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Expand"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Settings"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Enter split screen"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in picture-in-picture"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"If you don\'t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Manage"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubble dismissed."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Tap to restart this app and go full screen."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
index 87210d5..95c0d01 100644
--- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
+++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎‏‎‏‎‏‏‎‎‎‏‏‎‏‎‏‏‎‏‎Close‎‏‎‎‏‎"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‎‎‏‎‏‏‎‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‏‎‎‎‏‎‏‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎Expand‎‏‎‎‏‎"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‏‎‎‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‏‎‎‏‏‏‎‏‎‎‎‏‎‎‎‎‏‏‏‎‎Settings‎‏‎‎‏‎"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎Enter split screen‎‏‎‎‏‎"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎Menu‎‏‎‎‏‎"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="NAME">%s</xliff:g>‎‏‎‎‏‏‏‎ is in picture-in-picture‎‏‎‎‏‎"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎If you don\'t want ‎‏‎‎‏‏‎<xliff:g id="NAME">%s</xliff:g>‎‏‎‎‏‏‏‎ to use this feature, tap to open settings and turn it off.‎‏‎‎‏‎"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎Manage‎‏‎‎‏‎"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‎Bubble dismissed.‎‏‎‎‏‎"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎Tap to restart this app and go full screen.‎‏‎‎‏‎"</string>
-    <string name="got_it" msgid="4428750913636945527">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‎‏‏‏‎‎‏‏‏‎‏‏‏‎Got it‎‏‎‎‏‎"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
index ebe41e8..6e5347d 100644
--- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Cerrar"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Expandir"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Configuración"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Introducir pantalla dividida"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está en modo de Pantalla en pantalla"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> use esta función, presiona para abrir la configuración y desactivarla."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Administrar"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Se descartó el cuadro."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Presiona para reiniciar esta app y acceder al modo de pantalla completa."</string>
-    <string name="got_it" msgid="4428750913636945527">"Entendido"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml
index 5949099..4820a0f 100644
--- a/libs/WindowManager/Shell/res/values-es/strings.xml
+++ b/libs/WindowManager/Shell/res/values-es/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Cerrar"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Mostrar"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Ajustes"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Introducir pantalla dividida"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está en imagen en imagen"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca la notificación para abrir los ajustes y desactivarla."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestionar"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Burbuja cerrada."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Toca para reiniciar esta aplicación e ir a la pantalla completa."</string>
-    <string name="got_it" msgid="4428750913636945527">"Entendido"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml
index 8330981..4c94694 100644
--- a/libs/WindowManager/Shell/res/values-et/strings.xml
+++ b/libs/WindowManager/Shell/res/values-et/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Sule"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Laiendamine"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Seaded"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Ava jagatud ekraanikuva"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menüü"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> on režiimis Pilt pildis"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Kui te ei soovi, et rakendus <xliff:g id="NAME">%s</xliff:g> seda funktsiooni kasutaks, puudutage seadete avamiseks ja lülitage see välja."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Halda"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Mullist loobuti."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Puudutage rakenduse taaskäivitamiseks ja täisekraanrežiimi aktiveerimiseks."</string>
-    <string name="got_it" msgid="4428750913636945527">"Selge"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml
index 6649769..afc4292 100644
--- a/libs/WindowManager/Shell/res/values-eu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-eu/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Itxi"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Zabaldu"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Ezarpenak"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Sartu pantaila zatituan"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menua"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"Pantaila txiki gainjarrian dago <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ez baduzu nahi <xliff:g id="NAME">%s</xliff:g> zerbitzuak eginbide hori erabiltzea, sakatu hau ezarpenak ireki eta aukera desaktibatzeko."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Kudeatu"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Baztertu da globoa."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Saka ezazu aplikazioa berrabiarazteko, eta ezarri pantaila osoko modua."</string>
-    <string name="got_it" msgid="4428750913636945527">"Ados"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml
index f646039..e8a0682 100644
--- a/libs/WindowManager/Shell/res/values-fa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fa/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"بستن"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"بزرگ کردن"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"تنظیمات"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"ورود به حالت «صفحهٔ دونیمه»"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"منو"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> درحالت تصویر در تصویر است"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"اگر نمی‌خواهید <xliff:g id="NAME">%s</xliff:g> از این قابلیت استفاده کند، با ضربه زدن، تنظیمات را باز کنید و آن را خاموش کنید."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"مدیریت"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"حبابک رد شد."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"برای بازراه‌اندازی این برنامه و تغییر به حالت تمام‌صفحه، ضربه بزنید."</string>
-    <string name="got_it" msgid="4428750913636945527">"متوجه‌ام"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml
index 5f87163..f671105 100644
--- a/libs/WindowManager/Shell/res/values-fi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fi/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Sulje"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Laajenna"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Asetukset"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Avaa jaettu näyttö"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Valikko"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> on kuva kuvassa ‑tilassa"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Jos et halua, että <xliff:g id="NAME">%s</xliff:g> voi käyttää tätä ominaisuutta, avaa asetukset napauttamalla ja poista se käytöstä."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Ylläpidä"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Kupla ohitettu."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Napauta, niin sovellus käynnistyy uudelleen ja siirtyy koko näytön tilaan."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
index 68df591..0d0b718 100644
--- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Fermer"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Développer"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Paramètres"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Entrer dans l\'écran partagé"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> est en mode d\'incrustation d\'image"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Si vous ne voulez pas que <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, touchez l\'écran pour ouvrir les paramètres, puis désactivez-la."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gérer"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulle ignorée."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Touchez pour redémarrer cette application et passer en plein écran."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml
index eecc9cb..5652d7e 100644
--- a/libs/WindowManager/Shell/res/values-fr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-fr/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Fermer"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Développer"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Paramètres"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Accéder à l\'écran partagé"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> est en mode Picture-in-picture"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Si vous ne voulez pas que l\'application <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, appuyez ici pour ouvrir les paramètres et la désactiver."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gérer"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulle fermée."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Appuyez pour redémarrer cette application et activer le mode plein écran."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml
index 3583caf..81bd916 100644
--- a/libs/WindowManager/Shell/res/values-gl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gl/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Pechar"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Despregar"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Configuración"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Inserir pantalla dividida"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menú"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está na pantalla superposta"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Se non queres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca a configuración para abrir as opcións e desactivar a función."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Xestionar"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Ignorouse a burbulla."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Toca o botón para reiniciar esta aplicación e abrila en pantalla completa."</string>
-    <string name="got_it" msgid="4428750913636945527">"Entendido"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml
index ad5a68e40..3d408cf2 100644
--- a/libs/WindowManager/Shell/res/values-gu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-gu/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"બંધ કરો"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"વિસ્તૃત કરો"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"સેટિંગ"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"વિભાજિત સ્ક્રીન મોડમાં દાખલ થાઓ"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"મેનૂ"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ચિત્રમાં-ચિત્રની અંદર છે"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"જો તમે નથી ઇચ્છતા કે <xliff:g id="NAME">%s</xliff:g> આ સુવિધાનો ઉપયોગ કરે, તો સેટિંગ ખોલવા માટે ટૅપ કરો અને તેને બંધ કરો."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"મેનેજ કરો"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"બબલ છોડી દેવાયો."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"આ ઍપ ફરીથી ચાલુ કરવા માટે ટૅપ કરીને પૂર્ણ સ્ક્રીન કરો."</string>
-    <string name="got_it" msgid="4428750913636945527">"સમજાઈ ગયું"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml
index 55a30f2..8c93e0a 100644
--- a/libs/WindowManager/Shell/res/values-hi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hi/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"बंद करें"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"विस्तार करें"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"सेटिंग"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"स्प्लिट स्क्रीन मोड में जाएं"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"मेन्यू"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> \"पिक्चर में पिक्चर\" के अंदर है"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"अगर आप नहीं चाहते कि <xliff:g id="NAME">%s</xliff:g> इस सुविधा का उपयोग करे, तो सेटिंग खोलने के लिए टैप करें और उसे बंद करें ."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"मैनेज करें"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"बबल खारिज किया गया."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"इस ऐप्लिकेशन को रीस्टार्ट करने और फ़ुल स्क्रीन पर देखने के लिए टैप करें."</string>
-    <string name="got_it" msgid="4428750913636945527">"ठीक है"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml
index f6acb5c..1f8f982 100644
--- a/libs/WindowManager/Shell/res/values-hr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hr/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Zatvori"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Proširivanje"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Postavke"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Otvorite podijeljeni zaslon"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Izbornik"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> jest na slici u slici"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ako ne želite da aplikacija <xliff:g id="NAME">%s</xliff:g> upotrebljava tu značajku, dodirnite da biste otvorili postavke i isključili je."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljanje"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblačić odbačen."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Dodirnite da biste ponovo pokrenuli tu aplikaciju i prikazali je na cijelom zaslonu."</string>
-    <string name="got_it" msgid="4428750913636945527">"Shvaćam"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml
index 0c1c8a40..ebd02e5 100644
--- a/libs/WindowManager/Shell/res/values-hu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hu/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Bezárás"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Kibontás"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Beállítások"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Váltás osztott képernyőre"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"A(z) <xliff:g id="NAME">%s</xliff:g> kép a képben funkciót használ"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ha nem szeretné, hogy a(z) <xliff:g id="NAME">%s</xliff:g> használja ezt a funkciót, koppintson a beállítások megnyitásához, és kapcsolja ki."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Kezelés"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Buborék elvetve."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Koppintson az alkalmazás újraindításához és a teljes képernyős mód elindításához."</string>
-    <string name="got_it" msgid="4428750913636945527">"Rendben"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml
index 36204c1..29b2052 100644
--- a/libs/WindowManager/Shell/res/values-hy/strings.xml
+++ b/libs/WindowManager/Shell/res/values-hy/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Փակել"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Ընդարձակել"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Կարգավորումներ"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Մտնել տրոհված էկրանի ռեժիմ"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Ընտրացանկ"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>-ը «Նկար նկարի մեջ» ռեժիմում է"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Եթե չեք ցանկանում, որ <xliff:g id="NAME">%s</xliff:g>-ն օգտագործի այս գործառույթը, հպեք՝ կարգավորումները բացելու և այն անջատելու համար։"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Կառավարել"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Ամպիկը փակվեց։"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Հպեք՝ հավելվածը վերագործարկելու և լիաէկրան ռեժիմին անցնելու համար։"</string>
-    <string name="got_it" msgid="4428750913636945527">"Եղավ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml
index de962c4..e488855 100644
--- a/libs/WindowManager/Shell/res/values-in/strings.xml
+++ b/libs/WindowManager/Shell/res/values-in/strings.xml
@@ -20,6 +20,8 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Tutup"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Luaskan"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Setelan"</string>
+    <!-- no translation found for pip_phone_enter_split (7042877263880641911) -->
+    <skip />
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> adalah picture-in-picture"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, ketuk untuk membuka setelan dan menonaktifkannya."</string>
@@ -72,5 +74,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Kelola"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balon ditutup."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Ketuk untuk memulai ulang aplikasi ini dan membuka layar penuh."</string>
-    <string name="got_it" msgid="4428750913636945527">"Oke"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml
index c205d22..126d1f1 100644
--- a/libs/WindowManager/Shell/res/values-is/strings.xml
+++ b/libs/WindowManager/Shell/res/values-is/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Loka"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Stækka"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Stillingar"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Opna skjáskiptingu"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Valmynd"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> er með mynd í mynd"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ef þú vilt ekki að <xliff:g id="NAME">%s</xliff:g> noti þennan eiginleika skaltu ýta til að opna stillingarnar og slökkva á því."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Stjórna"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Blöðru lokað."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Ýttu til að endurræsa forritið og sýna það á öllum skjánum."</string>
-    <string name="got_it" msgid="4428750913636945527">"Ég skil"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml
index c788a03..ec221b1 100644
--- a/libs/WindowManager/Shell/res/values-it/strings.xml
+++ b/libs/WindowManager/Shell/res/values-it/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Chiudi"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Espandi"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Impostazioni"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Accedi a schermo diviso"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> è in Picture in picture"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Se non desideri che l\'app <xliff:g id="NAME">%s</xliff:g> utilizzi questa funzione, tocca per aprire le impostazioni e disattivarla."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestisci"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Fumetto ignorato."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Tocca per riavviare l\'app e passare alla modalità a schermo intero."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml
index b0c03ed..b87d10c 100644
--- a/libs/WindowManager/Shell/res/values-iw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-iw/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"סגירה"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"הרחבה"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"הגדרות"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"כניסה למסך המפוצל"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"תפריט"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> במצב תמונה בתוך תמונה"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"אם אינך רוצה שהתכונה הזו תשמש את <xliff:g id="NAME">%s</xliff:g>, יש להקיש כדי לפתוח את ההגדרות ולהשבית את התכונה."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ניהול"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"הבועה נסגרה."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"צריך להקיש כדי להפעיל מחדש את האפליקציה הזו ולעבור למסך מלא."</string>
-    <string name="got_it" msgid="4428750913636945527">"הבנתי"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml
index 36700bd..51ffca6 100644
--- a/libs/WindowManager/Shell/res/values-ja/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ja/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"閉じる"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"展開"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"設定"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"分割画面に切り替え"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"メニュー"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>はピクチャー イン ピクチャーで表示中です"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g>でこの機能を使用しない場合は、タップして設定を開いて OFF にしてください。"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ふきだしが非表示になっています。"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"タップしてこのアプリを再起動すると、全画面表示になります。"</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml
index af1377a..fc91d72 100644
--- a/libs/WindowManager/Shell/res/values-ka/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ka/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"დახურვა"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"გაშლა"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"პარამეტრები"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"გაყოფილ ეკრანში შესვლა"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"მენიუ"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> იყენებს რეჟიმს „ეკრანი ეკრანში“"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"თუ არ გსურთ, რომ <xliff:g id="NAME">%s</xliff:g> ამ ფუნქციას იყენებდეს, აქ შეხებით შეგიძლიათ გახსნათ პარამეტრები და გამორთოთ ის."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"მართვა"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ბუშტი დაიხურა."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"შეეხეთ ამ აპის გადასატვირთად და გადადით სრულ ეკრანზე."</string>
-    <string name="got_it" msgid="4428750913636945527">"გასაგებია"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml
index 6deb0b8..05a905d 100644
--- a/libs/WindowManager/Shell/res/values-kk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kk/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Жабу"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Жаю"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Параметрлер"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Бөлінген экранға кіру"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Mәзір"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> \"суреттегі сурет\" режимінде"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> деген пайдаланушының бұл мүмкіндікті пайдалануын қаламасаңыз, параметрлерді түртіп ашыңыз да, оларды өшіріңіз."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Басқару"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Қалқыма хабар жабылды."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Бұл қолданбаны қайта қосып, толық экранға өту үшін түртіңіз."</string>
-    <string name="got_it" msgid="4428750913636945527">"Түсінікті"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml
index c59d0fc..6a1cb2b 100644
--- a/libs/WindowManager/Shell/res/values-km/strings.xml
+++ b/libs/WindowManager/Shell/res/values-km/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"បិទ"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"ពង្រីក"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"ការកំណត់"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"ចូលមុខងារ​បំបែកអេក្រង់"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"ម៉ឺនុយ"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ស្ថិតក្នុងមុខងាររូបក្នុងរូប"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"ប្រសិនបើ​អ្នក​មិន​ចង់​ឲ្យ <xliff:g id="NAME">%s</xliff:g> ប្រើ​មុខងារ​នេះ​ សូមចុច​​បើក​ការកំណត់ រួច​បិទ​វា។"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"គ្រប់គ្រង"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"បានច្រានចោល​សារលេចឡើង។"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"ចុចដើម្បី​ចាប់ផ្ដើម​កម្មវិធី​នេះឡើងវិញ រួចចូលប្រើ​ពេញអេក្រង់។"</string>
-    <string name="got_it" msgid="4428750913636945527">"យល់ហើយ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml
index 5e655b4..aecb54b 100644
--- a/libs/WindowManager/Shell/res/values-kn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-kn/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"ಮುಚ್ಚಿ"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"ವಿಸ್ತೃತಗೊಳಿಸು"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"ಸ್ಪ್ಲಿಟ್‌-ಸ್ಕ್ರೀನ್‌ಗೆ ಪ್ರವೇಶಿಸಿ"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"ಮೆನು"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ಚಿತ್ರದಲ್ಲಿ ಚಿತ್ರವಾಗಿದೆ"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ಈ ವೈಶಿಷ್ಟ್ಯ ಬಳಸುವುದನ್ನು ನೀವು ಬಯಸದಿದ್ದರೆ, ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆಯಲು ಮತ್ತು ಅದನ್ನು ಆಫ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ನಿರ್ವಹಿಸಿ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ಬಬಲ್ ವಜಾಗೊಳಿಸಲಾಗಿದೆ."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"ಈ ಆ್ಯಪ್ ಅನ್ನು ಮರುಪ್ರಾರಂಭಿಸಲು ಮತ್ತು ಪೂರ್ಣ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ನೋಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
-    <string name="got_it" msgid="4428750913636945527">"ಅರ್ಥವಾಯಿತು"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml
index af34ef4..5af9ca2a 100644
--- a/libs/WindowManager/Shell/res/values-ko/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ko/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"닫기"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"펼치기"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"설정"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"화면 분할 모드로 전환"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"메뉴"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>에서 PIP 사용 중"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g>에서 이 기능이 사용되는 것을 원하지 않는 경우 탭하여 설정을 열고 기능을 사용 중지하세요."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"관리"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"대화창을 닫았습니다."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"탭하여 이 앱을 다시 시작하고 전체 화면으로 이동합니다."</string>
-    <string name="got_it" msgid="4428750913636945527">"확인"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml
index 8056d15..76f192e 100644
--- a/libs/WindowManager/Shell/res/values-ky/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ky/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Жабуу"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Жайып көрсөтүү"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Жөндөөлөр"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Экранды бөлүү режимине өтүү"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> – сүрөт ичиндеги сүрөт"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Эгер <xliff:g id="NAME">%s</xliff:g> колдонмосу бул функцияны пайдаланбасын десеңиз, жөндөөлөрдү ачып туруп, аны өчүрүп коюңуз."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Башкаруу"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Калкып чыкма билдирме жабылды."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Бул колдонмону өчүрүп күйгүзүп, толук экранга өтүү үчүн таптап коюңуз."</string>
-    <string name="got_it" msgid="4428750913636945527">"Түшүндүм"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml
index a578b0a..4ec6313 100644
--- a/libs/WindowManager/Shell/res/values-lo/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lo/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"ປິດ"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"ຂະຫຍາຍ"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"ການຕັ້ງຄ່າ"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"ເຂົ້າການແບ່ງໜ້າຈໍ"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"ເມນູ"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ແມ່ນເປັນການສະແດງຜົນຫຼາຍຢ່າງພ້ອມກັນ"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"ຫາກທ່ານບໍ່ຕ້ອງການ <xliff:g id="NAME">%s</xliff:g> ໃຫ້ໃຊ້ຄຸນສົມບັດນີ້, ໃຫ້ແຕະເພື່ອເປີດການຕັ້ງຄ່າ ແລ້ວປິດມັນໄວ້."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ຈັດການ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ປິດ Bubble ໄສ້ແລ້ວ."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"ແຕະເພື່ອຣີສະຕາດແອັບນີ້ ແລະ ໃຊ້ແບບເຕັມຈໍ."</string>
-    <string name="got_it" msgid="4428750913636945527">"ເຂົ້າໃຈແລ້ວ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml
index e037839..8630e91 100644
--- a/libs/WindowManager/Shell/res/values-lt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lt/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Uždaryti"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Išskleisti"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Nustatymai"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Įjungti išskaidyto ekrano režimą"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Meniu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> rodom. vaizdo vaizde"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Jei nenorite, kad „<xliff:g id="NAME">%s</xliff:g>“ naudotų šią funkciją, palietę atidarykite nustatymus ir išjunkite ją."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Tvarkyti"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Debesėlio atsisakyta."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Palieskite, kad paleistumėte iš naujo šią programą ir įjungtumėte viso ekrano režimą."</string>
-    <string name="got_it" msgid="4428750913636945527">"Supratau"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml
index 05472e4..b095b88 100644
--- a/libs/WindowManager/Shell/res/values-lv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-lv/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Aizvērt"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Izvērst"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Iestatījumi"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Piekļūt ekrāna sadalīšanas režīmam"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Izvēlne"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ir attēlā attēlā"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ja nevēlaties lietotnē <xliff:g id="NAME">%s</xliff:g> izmantot šo funkciju, pieskarieties, lai atvērtu iestatījumus un izslēgtu funkciju."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Pārvaldīt"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Burbulis ir noraidīts."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Pieskarieties, lai restartētu šo lietotni un pārietu pilnekrāna režīmā."</string>
-    <string name="got_it" msgid="4428750913636945527">"Labi"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml
index 9cb2c69..184fe9d 100644
--- a/libs/WindowManager/Shell/res/values-mk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mk/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Затвори"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Проширете"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Поставки"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Влези во поделен екран"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Мени"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> е во слика во слика"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ако не сакате <xliff:g id="NAME">%s</xliff:g> да ја користи функцијава, допрете за да ги отворите поставките и да ја исклучите."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Управувајте"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Балончето е отфрлено."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Допрете за да ја рестартирате апликацијава и да ја отворите на цел екран."</string>
-    <string name="got_it" msgid="4428750913636945527">"Сфатив"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml
index f0bf513..f1bfe9a 100644
--- a/libs/WindowManager/Shell/res/values-ml/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ml/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"അവസാനിപ്പിക്കുക"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"വികസിപ്പിക്കുക"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"ക്രമീകരണം"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"സ്ക്രീൻ വിഭജന മോഡിൽ പ്രവേശിക്കുക"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"മെനു"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ചിത്രത്തിനുള്ളിൽ ചിത്രം രീതിയിലാണ്"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ഈ ഫീച്ചർ ഉപയോഗിക്കേണ്ടെങ്കിൽ, ടാപ്പ് ചെയ്‌ത് ക്രമീകരണം തുറന്ന് അത് ഓഫാക്കുക."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"മാനേജ് ചെയ്യുക"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ബബിൾ ഡിസ്മിസ് ചെയ്തു."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"ഈ ആപ്പ് റീസ്‌റ്റാർട്ട് ചെയ്‌ത് പൂർണ്ണ സ്ക്രീനിലേക്ക് മാറാൻ ടാപ്പ് ചെയ്യുക."</string>
-    <string name="got_it" msgid="4428750913636945527">"മനസ്സിലായി"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml
index 68822cb..afe8584 100644
--- a/libs/WindowManager/Shell/res/values-mn/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mn/strings.xml
@@ -20,6 +20,8 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Хаах"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Дэлгэх"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Тохиргоо"</string>
+    <!-- no translation found for pip_phone_enter_split (7042877263880641911) -->
+    <skip />
     <string name="pip_menu_title" msgid="5393619322111827096">"Цэс"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> дэлгэцэн доторх дэлгэцэд байна"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Та <xliff:g id="NAME">%s</xliff:g>-д энэ онцлогийг ашиглуулахыг хүсэхгүй байвал тохиргоог нээгээд, үүнийг унтраана уу."</string>
@@ -72,5 +74,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Удирдах"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Бөмбөлгийг үл хэрэгссэн."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Энэ аппыг дахин эхлүүлж, бүтэн дэлгэцэд орохын тулд товшино уу."</string>
-    <string name="got_it" msgid="4428750913636945527">"Ойлголоо"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml
index a4b7be4..c11af7b 100644
--- a/libs/WindowManager/Shell/res/values-mr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-mr/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"बंद करा"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"विस्तृत करा"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"सेटिंग्ज"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"स्प्लिट स्क्रीन एंटर करा"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"मेनू"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> चित्रामध्ये चित्र मध्ये आहे"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g>ने हे वैशिष्ट्य वापरू नये असे तुम्हाला वाटत असल्यास, सेटिंग्ज उघडण्यासाठी टॅप करा आणि ते बंद करा."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"व्यवस्थापित करा"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"बबल डिसमिस केला."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"हे अ‍ॅप रीस्टार्ट करण्यासाठी आणि फुल स्क्रीन करण्यासाठी टॅप करा."</string>
-    <string name="got_it" msgid="4428750913636945527">"समजले"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml
index 2f33bfa..b495fef 100644
--- a/libs/WindowManager/Shell/res/values-ms/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ms/strings.xml
@@ -20,6 +20,8 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Tutup"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Kembangkan"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Tetapan"</string>
+    <!-- no translation found for pip_phone_enter_split (7042877263880641911) -->
+    <skip />
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> terdapat dalam gambar dalam gambar"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Jika anda tidak mahu <xliff:g id="NAME">%s</xliff:g> menggunakan ciri ini, ketik untuk membuka tetapan dan matikan ciri."</string>
@@ -72,5 +74,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Urus"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Gelembung diketepikan."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Ketik untuk memulakan semula apl ini dan menggunakan skrin penuh."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml
index 018ffc0..2849137 100644
--- a/libs/WindowManager/Shell/res/values-my/strings.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings.xml
@@ -20,8 +20,10 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"ပိတ်ရန်"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"ချဲ့ရန်"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"ဆက်တင်များ"</string>
+    <!-- no translation found for pip_phone_enter_split (7042877263880641911) -->
+    <skip />
     <string name="pip_menu_title" msgid="5393619322111827096">"မီနူး"</string>
-    <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> သည် တစ်ခုပေါ် တစ်ခုထပ်၍ ဖွင့်ထားသည်"</string>
+    <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> သည် နှစ်ခုထပ်၍ကြည့်ခြင်း ဖွင့်ထားသည်"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> အား ဤဝန်ဆောင်မှုကို အသုံးမပြုစေလိုလျှင် ဆက်တင်ကိုဖွင့်ရန် တို့ပြီး ၎င်းဝန်ဆောင်မှုကို ပိတ်လိုက်ပါ။"</string>
     <string name="pip_play" msgid="3496151081459417097">"ဖွင့်ရန်"</string>
     <string name="pip_pause" msgid="690688849510295232">"ခေတ္တရပ်ရန်"</string>
@@ -72,5 +74,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"စီမံရန်"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ပူဖောင်းကွက် ဖယ်လိုက်သည်။"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"ဤအက်ပ်ကို ပြန်စပြီး ဖန်သားပြင်အပြည့်လုပ်ရန် တို့ပါ။"</string>
-    <string name="got_it" msgid="4428750913636945527">"ရပြီ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-my/strings_tv.xml b/libs/WindowManager/Shell/res/values-my/strings_tv.xml
index 9569dc4..c18d539 100644
--- a/libs/WindowManager/Shell/res/values-my/strings_tv.xml
+++ b/libs/WindowManager/Shell/res/values-my/strings_tv.xml
@@ -17,7 +17,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="notification_channel_tv_pip" msgid="2576686079160402435">"တစ်ခုပေါ်တစ်ခုထပ်၍ ဖွင့်ခြင်း"</string>
+    <string name="notification_channel_tv_pip" msgid="2576686079160402435">"နှစ်ခုထပ်၍ကြည့်ခြင်း"</string>
     <string name="pip_notification_unknown_title" msgid="2729870284350772311">"(ခေါင်းစဉ်မဲ့ အစီအစဉ်)"</string>
     <string name="pip_close" msgid="9135220303720555525">"PIP ကိုပိတ်ပါ"</string>
     <string name="pip_fullscreen" msgid="7278047353591302554">"မျက်နှာပြင် အပြည့်"</string>
diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml
index a23ad90..87bc7da 100644
--- a/libs/WindowManager/Shell/res/values-nb/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nb/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Lukk"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Vis"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Innstillinger"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Aktivér delt skjerm"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Meny"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> er i bilde-i-bilde"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Hvis du ikke vil at <xliff:g id="NAME">%s</xliff:g> skal bruke denne funksjonen, kan du trykke for å åpne innstillingene og slå den av."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Administrer"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Boblen er avvist."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Trykk for å starte denne appen på nytt og vise den i fullskjerm."</string>
-    <string name="got_it" msgid="4428750913636945527">"Greit"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml
index 5b9b872..12df158 100644
--- a/libs/WindowManager/Shell/res/values-ne/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ne/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"बन्द गर्नुहोस्"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"विस्तृत गर्नुहोस्"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"सेटिङहरू"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"स्प्लिट स्क्रिन मोड प्रयोग गर्नुहोस्"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"मेनु"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> Picture-in-picture मा छ"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"तपाईं <xliff:g id="NAME">%s</xliff:g> ले सुविधा प्रयोग नगरोस् भन्ने चाहनुहुन्छ भने ट्याप गरेर सेटिङहरू खोल्नुहोस् र यसलाई निष्क्रिय पार्नुहोस्।"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"व्यवस्थापन गर्नुहोस्"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"बबल हटाइयो।"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"यो एप रिस्टार्ट गर्न ट्याप गर्नुहोस् र फुल स्क्रिन मोडमा जानुहोस्।"</string>
-    <string name="got_it" msgid="4428750913636945527">"बुझेँ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml
index 06aaad7..f83ad22 100644
--- a/libs/WindowManager/Shell/res/values-nl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-nl/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Sluiten"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Uitvouwen"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Instellingen"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Gesplitst scherm openen"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> is in scherm-in-scherm"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Als je niet wilt dat <xliff:g id="NAME">%s</xliff:g> deze functie gebruikt, tik je om de instellingen te openen en zet je de functie uit."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Beheren"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubbel gesloten."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Tik om deze app opnieuw te starten en te openen op het volledige scherm."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml
index ac1e84a..14f92c8 100644
--- a/libs/WindowManager/Shell/res/values-or/strings.xml
+++ b/libs/WindowManager/Shell/res/values-or/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"ବନ୍ଦ କରନ୍ତୁ"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"ବଢ଼ାନ୍ତୁ"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"ସେଟିଂସ୍"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"ସ୍ପ୍ଲିଟ ସ୍କ୍ରିନ ମୋଡ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"ମେନୁ"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> \"ଛବି-ଭିତରେ-ଛବି\"ରେ ଅଛି"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"ଏହି ବୈଶିଷ୍ଟ୍ୟ <xliff:g id="NAME">%s</xliff:g> ବ୍ୟବହାର ନକରିବାକୁ ଯଦି ଆପଣ ଚାହାଁନ୍ତି, ସେଟିଙ୍ଗ ଖୋଲିବାକୁ ଟାପ୍‍ କରନ୍ତୁ ଏବଂ ଏହା ଅଫ୍‍ କରିଦିଅନ୍ତୁ।"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ପରିଚାଳନା କରନ୍ତୁ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ବବଲ୍ ଖାରଜ କରାଯାଇଛି।"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"ଏହି ଆପକୁ ରିଷ୍ଟାର୍ଟ କରି ପୂର୍ଣ୍ଣ ସ୍କ୍ରିନ୍ କରିବାକୁ ଟାପ୍ କରନ୍ତୁ।"</string>
-    <string name="got_it" msgid="4428750913636945527">"ବୁଝିଗଲି"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml
index bf5b733c..e09f53adb 100644
--- a/libs/WindowManager/Shell/res/values-pa/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pa/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"ਬੰਦ ਕਰੋ"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"ਵਿਸਤਾਰ ਕਰੋ"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"ਸੈਟਿੰਗਾਂ"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਵਿੱਚ ਦਾਖਲ ਹੋਵੋ"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"ਮੀਨੂ"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ਤਸਵੀਰ-ਅੰਦਰ-ਤਸਵੀਰ ਵਿੱਚ ਹੈ"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"ਜੇਕਰ ਤੁਸੀਂ ਨਹੀਂ ਚਾਹੁੰਦੇ ਕਿ <xliff:g id="NAME">%s</xliff:g> ਐਪ ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦੀ ਵਰਤੋਂ ਕਰੇ, ਤਾਂ ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਇਸਨੂੰ ਬੰਦ ਕਰੋ।"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"ਪ੍ਰਬੰਧਨ ਕਰੋ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ਬਬਲ ਨੂੰ ਖਾਰਜ ਕੀਤਾ ਗਿਆ।"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"ਇਸ ਐਪ ਨੂੰ ਮੁੜ-ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਪੂਰੀ ਸਕ੍ਰੀਨ ਮੋਡ \'ਤੇ ਜਾਓ।"</string>
-    <string name="got_it" msgid="4428750913636945527">"ਸਮਝ ਲਿਆ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml
index cd659ba..a2ef997 100644
--- a/libs/WindowManager/Shell/res/values-pl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pl/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Zamknij"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Rozwiń"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Ustawienia"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Włącz podzielony ekran"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"Aplikacja <xliff:g id="NAME">%s</xliff:g> działa w trybie obraz w obrazie"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Jeśli nie chcesz, by aplikacja <xliff:g id="NAME">%s</xliff:g> korzystała z tej funkcji, otwórz ustawienia i wyłącz ją."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Zarządzaj"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Zamknięto dymek"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Kliknij, by uruchomić tę aplikację ponownie i przejść w tryb pełnoekranowy."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
index 3c8aaa4..1300e53 100644
--- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Fechar"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Abrir"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Configurações"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Dividir tela"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Se você não quer que o app <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gerenciar"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balão dispensado."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Toque para reiniciar o app e usar tela cheia."</string>
-    <string name="got_it" msgid="4428750913636945527">"Ok"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
index 1f5b0ab..f3314f8 100644
--- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Fechar"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Expandir"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Definições"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Aceder ao ecrã dividido"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"A app <xliff:g id="NAME">%s</xliff:g> está no modo de ecrã no ecrã"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Se não pretende que a app <xliff:g id="NAME">%s</xliff:g> utilize esta funcionalidade, toque para abrir as definições e desative-a."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gerir"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balão ignorado."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Toque para reiniciar esta app e ficar em ecrã inteiro."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml
index 3c8aaa4..1300e53 100644
--- a/libs/WindowManager/Shell/res/values-pt/strings.xml
+++ b/libs/WindowManager/Shell/res/values-pt/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Fechar"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Abrir"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Configurações"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Dividir tela"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> está em picture-in-picture"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Se você não quer que o app <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gerenciar"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balão dispensado."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Toque para reiniciar o app e usar tela cheia."</string>
-    <string name="got_it" msgid="4428750913636945527">"Ok"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml
index d694be1..01f96c8 100644
--- a/libs/WindowManager/Shell/res/values-ro/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ro/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Închideți"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Extindeți"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Setări"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Accesați ecranul împărțit"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Meniu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> este în modul picture-in-picture"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Dacă nu doriți ca <xliff:g id="NAME">%s</xliff:g> să utilizeze această funcție, atingeți pentru a deschide setările și dezactivați-o."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Gestionați"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balonul a fost respins."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Atingeți ca să reporniți aplicația și să treceți în modul ecran complet."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml
index e9bfffb..6a0e9c1 100644
--- a/libs/WindowManager/Shell/res/values-ru/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ru/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Закрыть"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Развернуть"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Настройки"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Включить разделение экрана"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> находится в режиме \"Картинка в картинке\""</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Чтобы отключить эту функцию для приложения \"<xliff:g id="NAME">%s</xliff:g>\", перейдите в настройки."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Настроить"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Всплывающий чат закрыт."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Нажмите, чтобы перезапустить приложение и перейти в полноэкранный режим."</string>
-    <string name="got_it" msgid="4428750913636945527">"ОК"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml
index ba178f0..d7ed246 100644
--- a/libs/WindowManager/Shell/res/values-si/strings.xml
+++ b/libs/WindowManager/Shell/res/values-si/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"වසන්න"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"දිග හරින්න"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"සැකසීම්"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"බෙදුම් තිරයට ඇතුළු වන්න"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"මෙනුව"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> පින්තූරය-තුළ-පින්තූරය තුළ වේ"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"ඔබට <xliff:g id="NAME">%s</xliff:g> මෙම විශේෂාංගය භාවිත කිරීමට අවශ්‍ය නැති නම්, සැකසීම් විවෘත කිරීමට තට්ටු කර එය ක්‍රියාවිරහිත කරන්න."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"කළමනා කරන්න"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"බුබුල ඉවත දමා ඇත."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"මෙම යෙදුම යළි ඇරඹීමට සහ පූර්ණ තිරයට යාමට තට්ටු කරන්න."</string>
-    <string name="got_it" msgid="4428750913636945527">"තේරුණා"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml
index e048ca1..13fd58f 100644
--- a/libs/WindowManager/Shell/res/values-sk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sk/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Zavrieť"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Rozbaliť"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Nastavenia"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Prejsť na rozdelenú obrazovku"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Ponuka"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je v režime obraz v obraze"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ak nechcete, aby aplikácia <xliff:g id="NAME">%s</xliff:g> používala túto funkciu, klepnutím otvorte nastavenia a vypnite ju."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Spravovať"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bublina bola zavretá."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Klepnutím reštartujete túto aplikáciu a prejdete do režimu celej obrazovky."</string>
-    <string name="got_it" msgid="4428750913636945527">"Dobre"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml
index ed05908..6a68069 100644
--- a/libs/WindowManager/Shell/res/values-sl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sl/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Zapri"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Razširi"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Nastavitve"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Vklopi razdeljen zaslon"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Meni"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> je v načinu slika v sliki"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Če ne želite, da aplikacija <xliff:g id="NAME">%s</xliff:g> uporablja to funkcijo, se dotaknite, da odprete nastavitve, in funkcijo izklopite."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Upravljanje"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Oblaček je bil opuščen."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Dotaknite se za vnovični zagon te aplikacije in preklop v celozaslonski način."</string>
-    <string name="got_it" msgid="4428750913636945527">"Razumem"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml
index 13e830c..2b0b551 100644
--- a/libs/WindowManager/Shell/res/values-sq/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sq/strings.xml
@@ -20,6 +20,8 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Mbyll"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Zgjero"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Cilësimet"</string>
+    <!-- no translation found for pip_phone_enter_split (7042877263880641911) -->
+    <skip />
     <string name="pip_menu_title" msgid="5393619322111827096">"Menyja"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> është në figurë brenda figurës"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Nëse nuk dëshiron që <xliff:g id="NAME">%s</xliff:g> ta përdorë këtë funksion, trokit për të hapur cilësimet dhe për ta çaktivizuar."</string>
@@ -72,5 +74,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Menaxho"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Flluska u hoq."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Trokit për ta rinisur këtë aplikacion dhe për të kaluar në ekranin e plotë."</string>
-    <string name="got_it" msgid="4428750913636945527">"E kuptova"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml
index be6857b..c0c1e3f 100644
--- a/libs/WindowManager/Shell/res/values-sr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sr/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Затвори"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Прошири"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Подешавања"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Уђи на подељени екран"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Мени"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> је слика у слици"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ако не желите да <xliff:g id="NAME">%s</xliff:g> користи ову функцију, додирните да бисте отворили подешавања и искључили је."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Управљајте"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Облачић је одбачен."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Додирните да бисте рестартовали апликацију и прешли у режим целог екрана."</string>
-    <string name="got_it" msgid="4428750913636945527">"Важи"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml
index e61e69b..34254d9 100644
--- a/libs/WindowManager/Shell/res/values-sv/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sv/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Stäng"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Utöka"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Inställningar"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Starta delad skärm"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Meny"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> visas i bild-i-bild"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Om du inte vill att den här funktionen används i <xliff:g id="NAME">%s</xliff:g> öppnar du inställningarna genom att trycka. Sedan inaktiverar du funktionen."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Hantera"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bubblan ignorerades."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Tryck för att starta om appen i helskärmsläge."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml
index 476af11..82a9f14 100644
--- a/libs/WindowManager/Shell/res/values-sw/strings.xml
+++ b/libs/WindowManager/Shell/res/values-sw/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Funga"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Panua"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Mipangilio"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Weka skrini iliyogawanywa"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menyu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> iko katika hali ya picha ndani ya picha nyingine"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Ikiwa hutaki <xliff:g id="NAME">%s</xliff:g> itumie kipengele hiki, gusa ili ufungue mipangilio na uizime."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Dhibiti"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Umeondoa kiputo."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Gusa ili uzime na uwashe programu hii, kisha nenda kwenye skrini nzima."</string>
-    <string name="got_it" msgid="4428750913636945527">"Nimeelewa"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml
index bc27389..0ed778a 100644
--- a/libs/WindowManager/Shell/res/values-ta/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ta/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"மூடு"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"விரி"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"அமைப்புகள்"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"திரைப் பிரிப்பு பயன்முறைக்குச் செல்"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"மெனு"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> தற்போது பிக்ச்சர்-இன்-பிக்ச்சரில் உள்ளது"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> இந்த அம்சத்தைப் பயன்படுத்த வேண்டாம் என நினைத்தால் இங்கு தட்டி அமைப்புகளைத் திறந்து இதை முடக்கவும்."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"நிர்வகி"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"குமிழ் நிராகரிக்கப்பட்டது."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"தட்டுவதன் மூலம் இந்த ஆப்ஸை மீண்டும் தொடங்கலாம், முழுத்திரையில் பார்க்கலாம்."</string>
-    <string name="got_it" msgid="4428750913636945527">"சரி"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml
index c2b6ffb..8fef67b 100644
--- a/libs/WindowManager/Shell/res/values-te/strings.xml
+++ b/libs/WindowManager/Shell/res/values-te/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"మూసివేయి"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"విస్తరింపజేయి"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"సెట్టింగ్‌లు"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"స్ప్లిట్ స్క్రీన్‌ను ఎంటర్ చేయండి"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"మెనూ"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> చిత్రంలో చిత్రం రూపంలో ఉంది"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ఈ లక్షణాన్ని ఉపయోగించకూడదు అని మీరు అనుకుంటే, సెట్టింగ్‌లను తెరవడానికి ట్యాప్ చేసి, దీన్ని ఆఫ్ చేయండి."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"మేనేజ్ చేయండి"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"బబుల్ విస్మరించబడింది."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"ఈ యాప్‌ను రీస్టార్ట్ చేయడానికి ట్యాప్ చేసి, ఆపై పూర్తి స్క్రీన్‌లోకి వెళ్లండి."</string>
-    <string name="got_it" msgid="4428750913636945527">"అర్థమైంది"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml
index 9017b3f..563ec2f 100644
--- a/libs/WindowManager/Shell/res/values-th/strings.xml
+++ b/libs/WindowManager/Shell/res/values-th/strings.xml
@@ -20,6 +20,8 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"ปิด"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"ขยาย"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"การตั้งค่า"</string>
+    <!-- no translation found for pip_phone_enter_split (7042877263880641911) -->
+    <skip />
     <string name="pip_menu_title" msgid="5393619322111827096">"เมนู"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> ใช้การแสดงภาพซ้อนภาพ"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"หากคุณไม่ต้องการให้ <xliff:g id="NAME">%s</xliff:g> ใช้ฟีเจอร์นี้ ให้แตะเพื่อเปิดการตั้งค่าแล้วปิดฟีเจอร์"</string>
@@ -72,5 +74,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"จัดการ"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"ปิดบับเบิลแล้ว"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"แตะเพื่อรีสตาร์ทแอปนี้และแสดงแบบเต็มหน้าจอ"</string>
-    <string name="got_it" msgid="4428750913636945527">"รับทราบ"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml
index c484caf..a9a36bb 100644
--- a/libs/WindowManager/Shell/res/values-tl/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tl/strings.xml
@@ -20,6 +20,8 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Isara"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Palawakin"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Mga Setting"</string>
+    <!-- no translation found for pip_phone_enter_split (7042877263880641911) -->
+    <skip />
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"Nasa picture-in-picture ang <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Kung ayaw mong magamit ni <xliff:g id="NAME">%s</xliff:g> ang feature na ito, i-tap upang buksan ang mga setting at i-off ito."</string>
@@ -72,5 +74,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Pamahalaan"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Na-dismiss na ang bubble."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"I-tap para i-restart ang app na ito at mag-full screen."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml
index ca856a1..971520a 100644
--- a/libs/WindowManager/Shell/res/values-tr/strings.xml
+++ b/libs/WindowManager/Shell/res/values-tr/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Kapat"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Genişlet"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Ayarlar"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Bölünmüş ekrana geç"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menü"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>, pencere içinde pencere özelliğini kullanıyor"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> uygulamasının bu özelliği kullanmasını istemiyorsanız dokunarak ayarları açın ve söz konusu özelliği kapatın."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Yönet"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Balon kapatıldı."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Bu uygulamayı yeniden başlatmak ve tam ekrana geçmek için dokunun."</string>
-    <string name="got_it" msgid="4428750913636945527">"Anladım"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml
index 08e8d29..3014735 100644
--- a/libs/WindowManager/Shell/res/values-uk/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uk/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Закрити"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Розгорнути"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Налаштування"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Розділити екран"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Меню"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"У додатку <xliff:g id="NAME">%s</xliff:g> є функція \"Картинка в картинці\""</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Щоб додаток <xliff:g id="NAME">%s</xliff:g> не використовував цю функцію, вимкніть її в налаштуваннях."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Налаштувати"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Спливаюче сповіщення закрито."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Натисніть, щоб перезапустити додаток і перейти в повноекранний режим."</string>
-    <string name="got_it" msgid="4428750913636945527">"Зрозуміло"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml
index 06c0927..07319ef 100644
--- a/libs/WindowManager/Shell/res/values-ur/strings.xml
+++ b/libs/WindowManager/Shell/res/values-ur/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"بند کریں"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"پھیلائیں"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"ترتیبات"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"اسپلٹ اسکرین تک رسائی"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"مینو"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> تصویر میں تصویر میں ہے"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"اگر آپ نہیں چاہتے ہیں کہ <xliff:g id="NAME">%s</xliff:g> اس خصوصیت کا استعمال کرے تو ترتیبات کھولنے کے لیے تھپتھپا کر اسے آف کرے۔"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"نظم کریں"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"بلبلہ برخاست کر دیا گیا۔"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"یہ ایپ دوبارہ شروع کرنے کے لیے تھپتھپائیں اور پوری اسکرین پر جائیں۔"</string>
-    <string name="got_it" msgid="4428750913636945527">"سمجھ آ گئی"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml
index 6a873a3..4c79d64 100644
--- a/libs/WindowManager/Shell/res/values-uz/strings.xml
+++ b/libs/WindowManager/Shell/res/values-uz/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Yopish"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Yoyish"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Sozlamalar"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Ajratilgan ekranga kirish"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menyu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> tasvir ustida tasvir rejimida"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"<xliff:g id="NAME">%s</xliff:g> ilovasi uchun bu funksiyani sozlamalar orqali faolsizlantirish mumkin."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Boshqarish"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Bulutcha yopildi."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Bu ilovani qaytadan ishga tushirish va butun ekranda ochish uchun bosing."</string>
-    <string name="got_it" msgid="4428750913636945527">"OK"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml
index 4d4eebc..b9f23cd 100644
--- a/libs/WindowManager/Shell/res/values-vi/strings.xml
+++ b/libs/WindowManager/Shell/res/values-vi/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Đóng"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Mở rộng"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Cài đặt"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Truy cập chế độ chia đôi màn hình"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Menu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g> đang ở chế độ ảnh trong ảnh"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Nếu bạn không muốn <xliff:g id="NAME">%s</xliff:g> sử dụng tính năng này, hãy nhấn để mở cài đặt và tắt tính năng này."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Quản lý"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Đã đóng bong bóng."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Nhấn để khởi động lại ứng dụng này và xem ở chế độ toàn màn hình."</string>
-    <string name="got_it" msgid="4428750913636945527">"Tôi hiểu"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
index 3b8c889..c007258 100644
--- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"关闭"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"展开"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"设置"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"进入分屏模式"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"菜单"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"<xliff:g id="NAME">%s</xliff:g>目前位于“画中画”中"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"如果您不想让“<xliff:g id="NAME">%s</xliff:g>”使用此功能,请点按以打开设置,然后关闭此功能。"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"已关闭对话泡。"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"点按即可重启此应用并进入全屏模式。"</string>
-    <string name="got_it" msgid="4428750913636945527">"知道了"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
index 9ba82b5..5e33677 100644
--- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"關閉"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"展開"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"設定"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"進入分割螢幕"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"選單"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"「<xliff:g id="NAME">%s</xliff:g>」目前在畫中畫模式"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"如果您不想「<xliff:g id="NAME">%s</xliff:g>」使用此功能,請輕按以開啟設定,然後停用此功能。"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"對話氣泡已關閉。"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"輕按即可重新開啟此應用程式並放大至全螢幕。"</string>
-    <string name="got_it" msgid="4428750913636945527">"知道了"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
index aa66653..2439a97 100644
--- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"關閉"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"展開"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"設定"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"進入分割畫面"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"選單"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"「<xliff:g id="NAME">%s</xliff:g>」目前在子母畫面中"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"如果你不想讓「<xliff:g id="NAME">%s</xliff:g>」使用這項功能,請輕觸開啟設定頁面,然後停用此功能。"</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"管理"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"已關閉泡泡。"</string>
     <string name="restart_button_description" msgid="5887656107651190519">"輕觸即可重新啟動這個應用程式並進入全螢幕模式。"</string>
-    <string name="got_it" msgid="4428750913636945527">"我知道了"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml
index c8199c8..20128f6 100644
--- a/libs/WindowManager/Shell/res/values-zu/strings.xml
+++ b/libs/WindowManager/Shell/res/values-zu/strings.xml
@@ -20,6 +20,7 @@
     <string name="pip_phone_close" msgid="5783752637260411309">"Vala"</string>
     <string name="pip_phone_expand" msgid="2579292903468287504">"Nweba"</string>
     <string name="pip_phone_settings" msgid="5468987116750491918">"Izilungiselelo"</string>
+    <string name="pip_phone_enter_split" msgid="7042877263880641911">"Faka ukuhlukanisa isikrini"</string>
     <string name="pip_menu_title" msgid="5393619322111827096">"Imenyu"</string>
     <string name="pip_notification_title" msgid="1347104727641353453">"U-<xliff:g id="NAME">%s</xliff:g> ungaphakathi kwesithombe esiphakathi kwesithombe"</string>
     <string name="pip_notification_message" msgid="8854051911700302620">"Uma ungafuni i-<xliff:g id="NAME">%s</xliff:g> ukuthi isebenzise lesi sici, thepha ukuze uvule izilungiselelo uphinde uyivale."</string>
@@ -72,5 +73,4 @@
     <string name="manage_bubbles_text" msgid="7730624269650594419">"Phatha"</string>
     <string name="accessibility_bubble_dismissed" msgid="8367471990421247357">"Ibhamuza licashisiwe."</string>
     <string name="restart_button_description" msgid="5887656107651190519">"Thepha ukuze uqale kabusha lolu hlelo lokusebenza uphinde uye kusikrini esigcwele."</string>
-    <string name="got_it" msgid="4428750913636945527">"Ngiyezwa"</string>
 </resources>
diff --git a/libs/WindowManager/Shell/res/values/colors.xml b/libs/WindowManager/Shell/res/values/colors.xml
index b25a218..23a2172 100644
--- a/libs/WindowManager/Shell/res/values/colors.xml
+++ b/libs/WindowManager/Shell/res/values/colors.xml
@@ -29,7 +29,10 @@
     <color name="bubbles_light">#FFFFFF</color>
     <color name="bubbles_dark">@color/GM2_grey_800</color>
     <color name="bubbles_icon_tint">@color/GM2_grey_700</color>
-    <color name="size_compat_hint_bubble">#30312B</color>
+
+    <!-- Size Compat Restart Button -->
+    <color name="size_compat_background">@android:color/system_neutral1_800</color>
+    <color name="size_compat_text">@android:color/system_neutral1_50</color>
 
     <!-- GM2 colors -->
     <color name="GM2_grey_200">#E8EAED</color>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
index f567877..c3ce362 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellInitImpl.java
@@ -74,7 +74,7 @@
             Optional<PipTouchHandler> pipTouchHandlerOptional,
             FullscreenTaskListener fullscreenTaskListener,
             Optional<FullscreenUnfoldController> fullscreenUnfoldTransitionController,
-            Optional<Optional<FreeformTaskListener>> freeformTaskListenerOptional,
+            Optional<FreeformTaskListener> freeformTaskListenerOptional,
             Optional<RecentTasksController> recentTasks,
             Transitions transitions,
             StartingWindowController startingWindow,
@@ -90,7 +90,7 @@
         mFullscreenTaskListener = fullscreenTaskListener;
         mPipTouchHandlerOptional = pipTouchHandlerOptional;
         mFullscreenUnfoldController = fullscreenUnfoldTransitionController;
-        mFreeformTaskListenerOptional = freeformTaskListenerOptional.flatMap(f -> f);
+        mFreeformTaskListenerOptional = freeformTaskListenerOptional;
         mRecentTasks = recentTasks;
         mTransitions = transitions;
         mMainExecutor = mainExecutor;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
index 75bc461..8e98b82 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java
@@ -29,6 +29,7 @@
 import android.annotation.Nullable;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.TaskInfo;
+import android.app.WindowConfiguration;
 import android.content.Context;
 import android.content.LocusId;
 import android.content.pm.ActivityInfo;
@@ -122,6 +123,16 @@
     }
 
     /**
+     * Callbacks for events in which the focus has changed.
+     */
+    public interface FocusListener {
+        /**
+         * Notifies when the task which is focused has changed.
+         */
+        void onFocusTaskChanged(RunningTaskInfo taskInfo);
+    }
+
+    /**
      * Keys map from either a task id or {@link TaskListenerType}.
      * @see #addListenerForTaskId
      * @see #addListenerForType
@@ -142,6 +153,8 @@
     /** @see #addLocusIdListener */
     private final ArraySet<LocusIdListener> mLocusIdListeners = new ArraySet<>();
 
+    private final ArraySet<FocusListener> mFocusListeners = new ArraySet<>();
+
     private final Object mLock = new Object();
     private StartingWindowController mStartingWindow;
 
@@ -155,6 +168,9 @@
     @Nullable
     private final Optional<RecentTasksController> mRecentTasks;
 
+    @Nullable
+    private RunningTaskInfo mLastFocusedTaskInfo;
+
     public ShellTaskOrganizer(ShellExecutor mainExecutor, Context context) {
         this(null /* taskOrganizerController */, mainExecutor, context, null /* sizeCompatUI */,
                 Optional.empty() /* recentTasksController */);
@@ -200,6 +216,14 @@
         }
     }
 
+    @Override
+    public void unregisterOrganizer() {
+        super.unregisterOrganizer();
+        if (mStartingWindow != null) {
+            mStartingWindow.clearAllWindows();
+        }
+    }
+
     public void createRootTask(int displayId, int windowingMode, TaskListener listener) {
         ProtoLog.v(WM_SHELL_TASK_ORG, "createRootTask() displayId=%d winMode=%d listener=%s",
                 displayId, windowingMode, listener.toString());
@@ -331,6 +355,27 @@
         }
     }
 
+    /**
+     * Adds a listener to be notified for task focus changes.
+     */
+    public void addFocusListener(FocusListener listener) {
+        synchronized (mLock) {
+            mFocusListeners.add(listener);
+            if (mLastFocusedTaskInfo != null) {
+                listener.onFocusTaskChanged(mLastFocusedTaskInfo);
+            }
+        }
+    }
+
+    /**
+     * Removes listener.
+     */
+    public void removeLocusIdListener(FocusListener listener) {
+        synchronized (mLock) {
+            mFocusListeners.remove(listener);
+        }
+    }
+
     @Override
     public void addStartingWindow(StartingWindowInfo info, IBinder appToken) {
         if (mStartingWindow != null) {
@@ -422,6 +467,18 @@
                 mRecentTasks.ifPresent(recentTasks ->
                         recentTasks.onTaskWindowingModeChanged(taskInfo));
             }
+            // TODO (b/207687679): Remove check for HOME once bug is fixed
+            final boolean isFocusedOrHome = taskInfo.isFocused
+                    || (taskInfo.topActivityType == WindowConfiguration.ACTIVITY_TYPE_HOME
+                    && taskInfo.isVisible);
+            final boolean focusTaskChanged = (mLastFocusedTaskInfo == null
+                    || mLastFocusedTaskInfo.taskId != taskInfo.taskId) && isFocusedOrHome;
+            if (focusTaskChanged) {
+                for (int i = 0; i < mFocusListeners.size(); i++) {
+                    mFocusListeners.valueAt(i).onFocusTaskChanged(taskInfo);
+                }
+                mLastFocusedTaskInfo = taskInfo;
+            }
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
index c8449a3..c807f66 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
@@ -291,8 +291,10 @@
         final String innerPrefix = prefix + "  ";
         final String childPrefix = innerPrefix + "  ";
         pw.println(prefix + this);
-        pw.println(innerPrefix + "Root taskId=" + getRootTaskId()
-                + " winMode=" + mRootTaskInfo.getWindowingMode());
+        if (mRootTaskInfo != null) {
+            pw.println(innerPrefix + "Root taskId=" + mRootTaskInfo.taskId
+                    + " winMode=" + mRootTaskInfo.getWindowingMode());
+        }
         if (mTaskInfo1 != null) {
             pw.println(innerPrefix + "1 taskId=" + mTaskInfo1.taskId
                     + " winMode=" + mTaskInfo1.getWindowingMode());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index caa5327..ec59fad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -111,8 +111,7 @@
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "BubbleController" : TAG_BUBBLES;
 
-    // TODO(b/173386799) keep in sync with Launcher3 and also don't do a broadcast
-    public static final String TASKBAR_CHANGED_BROADCAST = "taskbarChanged";
+    // TODO(b/173386799) keep in sync with Launcher3, not hooked up to anything
     public static final String EXTRA_TASKBAR_CREATED = "taskbarCreated";
     public static final String EXTRA_BUBBLE_OVERFLOW_OPENED = "bubbleOverflowOpened";
     public static final String EXTRA_TASKBAR_VISIBLE = "taskbarVisible";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
index 300319a..b40021e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java
@@ -32,6 +32,7 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.annotation.SuppressLint;
+import android.app.ActivityManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -529,9 +530,10 @@
                 // Otherwise, we either tapped the stack (which means we're collapsed
                 // and should expand) or the currently selected bubble (we're expanded
                 // and should collapse).
-                if (!maybeShowStackEdu()) {
+                if (!maybeShowStackEdu() && !mShowedUserEducationInTouchListenerActive) {
                     mBubbleData.setExpanded(!mBubbleData.isExpanded());
                 }
+                mShowedUserEducationInTouchListenerActive = false;
             }
         }
     };
@@ -549,6 +551,14 @@
                 return true;
             }
 
+            mShowedUserEducationInTouchListenerActive = false;
+            if (maybeShowStackEdu()) {
+                mShowedUserEducationInTouchListenerActive = true;
+                return true;
+            } else if (isStackEduShowing()) {
+                mStackEduView.hide(false /* fromExpansion */);
+            }
+
             // If the manage menu is visible, just hide it.
             if (mShowingManage) {
                 showManageMenu(false /* show */);
@@ -607,7 +617,8 @@
             // If we're expanding or collapsing, ignore all touch events.
             if (mIsExpansionAnimating
                     // Also ignore events if we shouldn't be draggable.
-                    || (mPositioner.showingInTaskbar() && !mIsExpanded)) {
+                    || (mPositioner.showingInTaskbar() && !mIsExpanded)
+                    || mShowedUserEducationInTouchListenerActive) {
                 return;
             }
 
@@ -628,7 +639,7 @@
                     mExpandedAnimationController.dragBubbleOut(
                             v, viewInitialX + dx, viewInitialY + dy);
                 } else {
-                    if (mStackEduView != null) {
+                    if (isStackEduShowing()) {
                         mStackEduView.hide(false /* fromExpansion */);
                     }
                     mStackAnimationController.moveStackFromTouch(
@@ -646,6 +657,10 @@
                     || (mPositioner.showingInTaskbar() && !mIsExpanded)) {
                 return;
             }
+            if (mShowedUserEducationInTouchListenerActive) {
+                mShowedUserEducationInTouchListenerActive = false;
+                return;
+            }
 
             // First, see if the magnetized object consumes the event - if so, the bubble was
             // released in the target or flung out of it, and we should ignore the event.
@@ -738,6 +753,7 @@
     private ImageView mManageSettingsIcon;
     private TextView mManageSettingsText;
     private boolean mShowingManage = false;
+    private boolean mShowedUserEducationInTouchListenerActive = false;
     private PhysicsAnimator.SpringConfig mManageSpringConfig = new PhysicsAnimator.SpringConfig(
             SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_LOW_BOUNCY);
     private BubblePositioner mPositioner;
@@ -929,10 +945,12 @@
                 showManageMenu(false /* show */);
             } else if (mManageEduView != null && mManageEduView.getVisibility() == VISIBLE) {
                 mManageEduView.hide();
-            } else if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) {
+            } else if (isStackEduShowing()) {
                 mStackEduView.hide(false /* isExpanding */);
             } else if (mBubbleData.isExpanded()) {
                 mBubbleData.setExpanded(false);
+            } else {
+                maybeShowStackEdu();
             }
         });
 
@@ -1116,6 +1134,9 @@
      * Whether the educational view should show for the expanded view "manage" menu.
      */
     private boolean shouldShowManageEdu() {
+        if (ActivityManager.isRunningInTestHarness()) {
+            return false;
+        }
         final boolean seen = getPrefBoolean(ManageEducationViewKt.PREF_MANAGED_EDUCATION);
         final boolean shouldShow = (!seen || BubbleDebugConfig.forceShowUserEducation(mContext))
                 && mExpandedBubble != null;
@@ -1140,6 +1161,9 @@
      * Whether education view should show for the collapsed stack.
      */
     private boolean shouldShowStackEdu() {
+        if (ActivityManager.isRunningInTestHarness()) {
+            return false;
+        }
         final boolean seen = getPrefBoolean(StackEducationViewKt.PREF_STACK_EDUCATION);
         final boolean shouldShow = !seen || BubbleDebugConfig.forceShowUserEducation(mContext);
         if (BubbleDebugConfig.DEBUG_USER_EDUCATION) {
@@ -1157,7 +1181,7 @@
      * @return true if education view for collapsed stack should show and was not showing before.
      */
     private boolean maybeShowStackEdu() {
-        if (!shouldShowStackEdu()) {
+        if (!shouldShowStackEdu() || isExpanded()) {
             return false;
         }
         if (mStackEduView == null) {
@@ -1168,9 +1192,13 @@
         return mStackEduView.show(mPositioner.getDefaultStartPosition());
     }
 
+    private boolean isStackEduShowing() {
+        return mStackEduView != null && mStackEduView.getVisibility() == VISIBLE;
+    }
+
     // Recreates & shows the education views. Call when a theme/config change happens.
     private void updateUserEdu() {
-        if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) {
+        if (isStackEduShowing()) {
             removeView(mStackEduView);
             mStackEduView = new StackEducationView(mContext, mPositioner, mBubbleController);
             addView(mStackEduView);
@@ -1852,7 +1880,7 @@
         cancelDelayedExpandCollapseSwitchAnimations();
         final boolean showVertically = mPositioner.showBubblesVertically();
         mIsExpanded = true;
-        if (mStackEduView != null) {
+        if (isStackEduShowing()) {
             mStackEduView.hide(true /* fromExpansion */);
         }
         beforeExpandedViewAnimation();
@@ -2390,7 +2418,7 @@
         if (flyoutMessage == null
                 || flyoutMessage.message == null
                 || !bubble.showFlyout()
-                || (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE)
+                || isStackEduShowing()
                 || isExpanded()
                 || mIsExpansionAnimating
                 || mIsGestureInProgress
@@ -2512,7 +2540,7 @@
      * them.
      */
     public void getTouchableRegion(Rect outRect) {
-        if (mStackEduView != null && mStackEduView.getVisibility() == VISIBLE) {
+        if (isStackEduShowing()) {
             // When user education shows then capture all touches
             outRect.set(0, 0, getWidth(), getHeight());
             return;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt
index f6a90b7..3846de7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/StackEducationView.kt
@@ -125,6 +125,7 @@
      * @return true if user education was shown, false otherwise.
      */
     fun show(stackPosition: PointF): Boolean {
+        isHiding = false
         if (visibility == VISIBLE) return false
 
         controller.updateWindowFlagsForBackpress(true /* interceptBack */)
@@ -164,6 +165,7 @@
      */
     fun hide(isExpanding: Boolean) {
         if (visibility != VISIBLE || isHiding) return
+        isHiding = true
 
         controller.updateWindowFlagsForBackpress(false /* interceptBack */)
         animate()
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index 7784665..6f4e22f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -93,6 +93,19 @@
     private boolean mReverseDefaultRotation = false;
     private InsetsState mInsetsState = new InsetsState();
 
+    /**
+     * Different from {@link #equals(Object)}, this method compares the basic geometry properties
+     * of two {@link DisplayLayout} objects including width, height, rotation, density and cutout.
+     * @return {@code true} if the given {@link DisplayLayout} is identical geometry wise.
+     */
+    public boolean isSameGeometry(@NonNull DisplayLayout other) {
+        return mWidth == other.mWidth
+                && mHeight == other.mHeight
+                && mRotation == other.mRotation
+                && mDensityDpi == other.mDensityDpi
+                && Objects.equals(mCutout, other.mCutout);
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
index 33ce383..1039e2a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java
@@ -356,9 +356,6 @@
         public void dispatchGetNewSurface() {}
 
         @Override
-        public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {}
-
-        @Override
         public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {}
 
         @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 625bcee..3579bf4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -34,6 +34,7 @@
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -61,6 +62,8 @@
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
 
+import java.io.PrintWriter;
+
 /**
  * Records and handles layout of splits. Helps to calculate proper bounds when configuration or
  * divide position changes.
@@ -318,6 +321,16 @@
         mSplitLayoutHandler.onLayoutSizeChanged(this);
     }
 
+    /** Sets divide position base on the ratio within root bounds. */
+    public void setDivideRatio(float ratio) {
+        final int position = isLandscape()
+                ? mRootBounds.left + (int) (mRootBounds.width() * ratio)
+                : mRootBounds.top + (int) (mRootBounds.height() * ratio);
+        DividerSnapAlgorithm.SnapTarget snapTarget =
+                mDividerSnapAlgorithm.calculateNonDismissingSnapTarget(position);
+        setDividePosition(snapTarget.position);
+    }
+
     /** Resets divider position. */
     public void resetDividerPosition() {
         mDividePosition = mDividerSnapAlgorithm.getMiddleTarget().position;
@@ -415,6 +428,19 @@
         return bounds.width() > bounds.height();
     }
 
+    /** Reverse the split position. */
+    @SplitPosition
+    public static int reversePosition(@SplitPosition int position) {
+        switch (position) {
+            case SPLIT_POSITION_TOP_OR_LEFT:
+                return SPLIT_POSITION_BOTTOM_OR_RIGHT;
+            case SPLIT_POSITION_BOTTOM_OR_RIGHT:
+                return SPLIT_POSITION_TOP_OR_LEFT;
+            default:
+                return SPLIT_POSITION_UNDEFINED;
+        }
+    }
+
     /**
      * Return if this layout is landscape.
      */
@@ -502,6 +528,13 @@
         }
     }
 
+    /** Dumps the current split bounds recorded in this layout. */
+    public void dump(@NonNull PrintWriter pw, String prefix) {
+        pw.println(prefix + "bounds1=" + mBounds1.toShortString());
+        pw.println(prefix + "dividerBounds=" + mDividerBounds.toShortString());
+        pw.println(prefix + "bounds2=" + mBounds2.toShortString());
+    }
+
     /** Handles layout change event. */
     public interface SplitLayoutHandler {
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/DynamicOverride.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/DynamicOverride.java
new file mode 100644
index 0000000..806f795
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/DynamicOverride.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 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.wm.shell.dagger;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+import javax.inject.Qualifier;
+
+/**
+ * This is a qualifier that Shell uses to workaround an issue with providing nullable optionals
+ * which are by default unbound.
+ *
+ * For example, ideally we would have this scenario:
+ * BaseModule:
+ *   @BindsOptionalOf
+ *   abstract Optional<Interface> optionalInterface();
+ *
+ * SpecializedModule:
+ *   @Provides
+ *   static Interface providesInterface() {
+ *       return new InterfaceImpl();
+ *   }
+ *
+ * However, if the interface is supposed to be provided dynamically, then Dagger is not able to bind
+ * the optional interface to a null instance, and @BindsOptionalOf does not support @Nullable
+ * instances of the interface provided by the specialized module.
+ *
+ * For example, this does not work:
+ * BaseModule:
+ *   @BindsOptionalOf
+ *   abstract Optional<Interface> optionalInterface();
+ *
+ * SpecializedModule:
+ *   @Provides
+ *   static Interface providesInterface() {
+ *       if (systemSupportsInterfaceFeature) {
+ *           return new InterfaceImpl();
+ *       } else {
+ *           return null;
+ *       }
+ *   }
+ *
+ * To workaround this, we can instead upstream the check (assuming it can be upstreamed into the
+ * base module), and then always provide a non-null instance in the specialized module.
+ *
+ * For example:
+ * BaseModule:
+ *   @BindsOptionalOf
+ *   @DynamicOverride
+ *   abstract Interface dynamicInterface();
+ *
+ *   @Provides
+ *   static Optional<Interface> providesOptionalInterface(
+ *           @DynamicOverride Optional<Interface> interface) {
+ *       if (systemSupportsInterfaceFeature) {
+ *           return interface;
+ *       }
+ *       return Optional.empty();
+ *   }
+ *
+ * SpecializedModule:
+ *   @Provides
+ *   @DynamicOverride
+ *   static Interface providesInterface() {
+ *       return new InterfaceImpl();
+ *   }
+ *
+ * This is also useful in cases where there needs to be a default implementation in the base module
+ * which is also overridable in the specialized module.  This isn't generally recommended, but
+ * due to the nature of Shell modules being referenced from a number of various projects, this
+ * can be useful for *required* components that
+ * 1) clearly identifies which are intended for overriding in the base module, and
+ * 2) allows us to declare a default implementation in the base module, without having to force
+ *    every SysUI impl to explicitly provide it (if a large number of them share the default impl)
+ *
+ * For example, this uses the same setup as above, but the interface provided (if bound) is used
+ * otherwise the default is created:
+ *   @BindsOptionalOf
+ *   @DynamicOverride
+ *   abstract Interface dynamicInterface();
+ *
+ *   @Provides
+ *   static Optional<Interface> providesOptionalInterface(
+ *           @DynamicOverride Optional<Interface> overrideInterfaceImpl) {
+ *       if (overrideInterfaceImpl.isPresent()) {
+ *           return overrideInterfaceImpl.get();
+ *       }
+ *       return new DefaultImpl();
+ *   }
+ *
+ * SpecializedModule:
+ *   @Provides
+ *   @DynamicOverride
+ *   static Interface providesInterface() {
+ *       return new SuperSpecialImpl();
+ *   }
+ */
+@Documented
+@Inherited
+@Qualifier
+@Retention(RetentionPolicy.RUNTIME)
+public @interface DynamicOverride {}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
index 6997d60..15bfeb2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
@@ -16,25 +16,16 @@
 
 package com.android.wm.shell.dagger;
 
-import android.animation.AnimationHandler;
-import android.content.Context;
 import android.view.IWindowManager;
 
-import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.ShellExecutor;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.common.SystemWindows;
-import com.android.wm.shell.common.TaskStackListenerImpl;
 import com.android.wm.shell.common.TransactionPool;
-import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
 import com.android.wm.shell.common.annotations.ShellMainThread;
-import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
 import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
 import com.android.wm.shell.startingsurface.tv.TvStartingWindowTypeAlgorithm;
-import com.android.wm.shell.transition.Transitions;
 
 import dagger.Module;
 import dagger.Provides;
@@ -51,42 +42,12 @@
 public class TvWMShellModule {
 
     //
-    // Internal common - Components used internally by multiple shell features
-    //
-
-    @WMSingleton
-    @Provides
-    static DisplayImeController provideDisplayImeController(IWindowManager wmService,
-            DisplayController displayController, DisplayInsetsController displayInsetsController,
-            @ShellMainThread ShellExecutor mainExecutor, TransactionPool transactionPool) {
-        return new DisplayImeController(wmService, displayController, displayInsetsController,
-                mainExecutor, transactionPool);
-    }
-
-    //
-    // Split/multiwindow
-    //
-
-    @WMSingleton
-    @Provides
-    static LegacySplitScreenController provideSplitScreen(Context context,
-            DisplayController displayController, SystemWindows systemWindows,
-            DisplayImeController displayImeController, TransactionPool transactionPool,
-            ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue,
-            TaskStackListenerImpl taskStackListener, Transitions transitions,
-            @ShellMainThread ShellExecutor mainExecutor,
-            @ChoreographerSfVsync AnimationHandler sfVsyncAnimationHandler) {
-        return new LegacySplitScreenController(context, displayController, systemWindows,
-                displayImeController, transactionPool, shellTaskOrganizer, syncQueue,
-                taskStackListener, transitions, mainExecutor, sfVsyncAnimationHandler);
-    }
-
-    //
     // Starting Windows (Splash Screen)
     //
 
     @WMSingleton
     @Provides
+    @DynamicOverride
     static StartingWindowTypeAlgorithm provideStartingWindowTypeAlgorithm() {
         return new TvStartingWindowTypeAlgorithm();
     };
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index ac2e448..9ceed24 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -16,16 +16,16 @@
 
 package com.android.wm.shell.dagger;
 
+import static com.android.wm.shell.onehanded.OneHandedController.SUPPORT_ONE_HANDED_MODE;
+
 import android.app.ActivityTaskManager;
 import android.content.Context;
-import android.content.pm.LauncherApps;
 import android.content.pm.PackageManager;
 import android.os.Handler;
+import android.os.SystemProperties;
 import android.view.IWindowManager;
-import android.view.WindowManager;
 
 import com.android.internal.logging.UiEventLogger;
-import com.android.internal.statusbar.IStatusBarService;
 import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.RootDisplayAreaOrganizer;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
@@ -74,26 +74,23 @@
 import com.android.wm.shell.pip.phone.PipTouchHandler;
 import com.android.wm.shell.recents.RecentTasks;
 import com.android.wm.shell.recents.RecentTasksController;
+import com.android.wm.shell.sizecompatui.SizeCompatUI;
 import com.android.wm.shell.sizecompatui.SizeCompatUIController;
 import com.android.wm.shell.splitscreen.SplitScreen;
 import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.splitscreen.StageTaskUnfoldController;
 import com.android.wm.shell.startingsurface.StartingSurface;
 import com.android.wm.shell.startingsurface.StartingWindowController;
 import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
+import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
 import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
 import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelperController;
 import com.android.wm.shell.transition.ShellTransitions;
 import com.android.wm.shell.transition.Transitions;
 import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
-import com.android.wm.shell.unfold.UnfoldBackgroundController;
 
 import java.util.Optional;
 
-import javax.inject.Provider;
-
 import dagger.BindsOptionalOf;
-import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
 
@@ -128,6 +125,28 @@
         return new DisplayInsetsController(wmService, displayController, mainExecutor);
     }
 
+    // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+    @BindsOptionalOf
+    @DynamicOverride
+    abstract DisplayImeController optionalDisplayImeController();
+
+    @WMSingleton
+    @Provides
+    static DisplayImeController provideDisplayImeController(
+            @DynamicOverride Optional<DisplayImeController> overrideDisplayImeController,
+            IWindowManager wmService,
+            DisplayController displayController,
+            DisplayInsetsController displayInsetsController,
+            @ShellMainThread ShellExecutor mainExecutor,
+            TransactionPool transactionPool
+    ) {
+        if (overrideDisplayImeController.isPresent()) {
+            return overrideDisplayImeController.get();
+        }
+        return new DisplayImeController(wmService, displayController, displayInsetsController,
+                mainExecutor, transactionPool);
+    }
+
     @WMSingleton
     @Provides
     static DisplayLayout provideDisplayLayout() {
@@ -153,11 +172,18 @@
 
     @WMSingleton
     @Provides
+    static SizeCompatUI provideSizeCompatUI(SizeCompatUIController sizeCompatUIController) {
+        return sizeCompatUIController.asSizeCompatUI();
+    }
+
+    @WMSingleton
+    @Provides
     static SizeCompatUIController provideSizeCompatUIController(Context context,
             DisplayController displayController, DisplayInsetsController displayInsetsController,
-            DisplayImeController imeController, SyncTransactionQueue syncQueue) {
+            DisplayImeController imeController, SyncTransactionQueue syncQueue,
+            @ShellMainThread ShellExecutor mainExecutor) {
         return new SizeCompatUIController(context, displayController, displayInsetsController,
-                imeController, syncQueue);
+                imeController, syncQueue, mainExecutor);
     }
 
     @WMSingleton
@@ -202,7 +228,7 @@
     }
 
     //
-    // Bubbles
+    // Bubbles (optional feature)
     //
 
     @WMSingleton
@@ -211,100 +237,76 @@
         return bubbleController.map((controller) -> controller.asBubbles());
     }
 
-    // Note: Handler needed for LauncherApps.register
-    @WMSingleton
-    @Provides
-    static Optional<BubbleController> provideBubbleController(Context context,
-            FloatingContentCoordinator floatingContentCoordinator,
-            IStatusBarService statusBarService,
-            WindowManager windowManager,
-            WindowManagerShellWrapper windowManagerShellWrapper,
-            LauncherApps launcherApps,
-            TaskStackListenerImpl taskStackListener,
-            UiEventLogger uiEventLogger,
-            ShellTaskOrganizer organizer,
-            DisplayController displayController,
-            @ShellMainThread ShellExecutor mainExecutor,
-            @ShellMainThread Handler mainHandler,
-            SyncTransactionQueue syncQueue) {
-        return Optional.of(BubbleController.create(context, null /* synchronizer */,
-                floatingContentCoordinator, statusBarService, windowManager,
-                windowManagerShellWrapper, launcherApps, taskStackListener,
-                uiEventLogger, organizer, displayController, mainExecutor, mainHandler, syncQueue));
-    }
+    @BindsOptionalOf
+    abstract BubbleController optionalBubblesController();
 
     //
     // Fullscreen
     //
 
+    // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+    @BindsOptionalOf
+    @DynamicOverride
+    abstract FullscreenTaskListener optionalFullscreenTaskListener();
+
     @WMSingleton
     @Provides
     static FullscreenTaskListener provideFullscreenTaskListener(
+            @DynamicOverride Optional<FullscreenTaskListener> fullscreenTaskListener,
             SyncTransactionQueue syncQueue,
             Optional<FullscreenUnfoldController> optionalFullscreenUnfoldController,
-            Optional<RecentTasksController> recentTasksOptional
-    ) {
-        return new FullscreenTaskListener(syncQueue, optionalFullscreenUnfoldController,
-                recentTasksOptional);
+            Optional<RecentTasksController> recentTasksOptional) {
+        if (fullscreenTaskListener.isPresent()) {
+            return fullscreenTaskListener.get();
+        } else {
+            return new FullscreenTaskListener(syncQueue, optionalFullscreenUnfoldController,
+                    recentTasksOptional);
+        }
     }
 
     //
     // Unfold transition
     //
 
+    @BindsOptionalOf
+    abstract ShellUnfoldProgressProvider optionalShellUnfoldProgressProvider();
+
+    // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+    @BindsOptionalOf
+    @DynamicOverride
+    abstract FullscreenUnfoldController optionalFullscreenUnfoldController();
+
     @WMSingleton
     @Provides
     static Optional<FullscreenUnfoldController> provideFullscreenUnfoldController(
-            Context context,
-            Optional<ShellUnfoldProgressProvider> progressProvider,
-            Lazy<UnfoldBackgroundController> unfoldBackgroundController,
-            DisplayInsetsController displayInsetsController,
-            @ShellMainThread ShellExecutor mainExecutor
-    ) {
-        return progressProvider.map(shellUnfoldTransitionProgressProvider ->
-                new FullscreenUnfoldController(context, mainExecutor,
-                        unfoldBackgroundController.get(), shellUnfoldTransitionProgressProvider,
-                        displayInsetsController));
-    }
-
-    @Provides
-    static Optional<StageTaskUnfoldController> provideStageTaskUnfoldController(
-            Optional<ShellUnfoldProgressProvider> progressProvider,
-            Context context,
-            TransactionPool transactionPool,
-            Lazy<UnfoldBackgroundController> unfoldBackgroundController,
-            DisplayInsetsController displayInsetsController,
-            @ShellMainThread ShellExecutor mainExecutor
-    ) {
-        return progressProvider.map(shellUnfoldTransitionProgressProvider ->
-                new StageTaskUnfoldController(
-                        context,
-                        transactionPool,
-                        shellUnfoldTransitionProgressProvider,
-                        displayInsetsController,
-                        unfoldBackgroundController.get(),
-                        mainExecutor
-                ));
-    }
-
-    @WMSingleton
-    @Provides
-    static UnfoldBackgroundController provideUnfoldBackgroundController(
-            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
-            Context context
-    ) {
-        return new UnfoldBackgroundController(
-                context,
-                rootTaskDisplayAreaOrganizer
-        );
+            @DynamicOverride Optional<FullscreenUnfoldController> fullscreenUnfoldController,
+            Optional<ShellUnfoldProgressProvider> progressProvider) {
+        if (progressProvider.isPresent()
+                && progressProvider.get() != ShellUnfoldProgressProvider.NO_PROVIDER) {
+            return fullscreenUnfoldController;
+        }
+        return Optional.empty();
     }
 
     //
     // Freeform (optional feature)
     //
 
+    // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
     @BindsOptionalOf
-    abstract Optional<FreeformTaskListener> optionalFreeformTaskListener();
+    @DynamicOverride
+    abstract FreeformTaskListener optionalFreeformTaskListener();
+
+    @WMSingleton
+    @Provides
+    static Optional<FreeformTaskListener> provideFreeformTaskListener(
+            @DynamicOverride Optional<FreeformTaskListener> freeformTaskListener,
+            Context context) {
+        if (FreeformTaskListener.isFreeformEnabled(context)) {
+            return freeformTaskListener;
+        }
+        return Optional.empty();
+    }
 
     //
     // Hide display cutout
@@ -335,20 +337,22 @@
         return oneHandedController.map((controller) -> controller.asOneHanded());
     }
 
-    // Needs the shell main handler for ContentObserver callbacks
+    // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+    @BindsOptionalOf
+    @DynamicOverride
+    abstract OneHandedController optionalOneHandedController();
+
     @WMSingleton
     @Provides
-    static Optional<OneHandedController> provideOneHandedController(Context context,
-            WindowManager windowManager, DisplayController displayController,
-            DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener,
-            UiEventLogger uiEventLogger,
-            @ShellMainThread ShellExecutor mainExecutor,
-            @ShellMainThread Handler mainHandler) {
-        return Optional.ofNullable(OneHandedController.create(context, windowManager,
-                displayController, displayLayout, taskStackListener, uiEventLogger, mainExecutor,
-                mainHandler));
+    static Optional<OneHandedController> providesOneHandedController(
+            @DynamicOverride Optional<OneHandedController> oneHandedController) {
+        if (SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
+            return oneHandedController;
+        }
+        return Optional.empty();
     }
 
+
     //
     // Task to Surface communication
     //
@@ -366,15 +370,6 @@
         return Optional.ofNullable(new TaskSurfaceHelperController(taskOrganizer, mainExecutor));
     }
 
-    @WMSingleton
-    @Provides
-    static Optional<DisplayAreaHelper> provideDisplayAreaHelper(
-            @ShellMainThread ShellExecutor mainExecutor,
-            RootDisplayAreaOrganizer rootDisplayAreaOrganizer) {
-        return Optional.ofNullable(new DisplayAreaHelperController(mainExecutor,
-                rootDisplayAreaOrganizer));
-    }
-
     //
     // Pip (optional feature)
     //
@@ -460,7 +455,7 @@
     }
 
     //
-    // Split/multiwindow
+    // Display areas
     //
 
     @WMSingleton
@@ -479,31 +474,38 @@
 
     @WMSingleton
     @Provides
+    static Optional<DisplayAreaHelper> provideDisplayAreaHelper(
+            @ShellMainThread ShellExecutor mainExecutor,
+            RootDisplayAreaOrganizer rootDisplayAreaOrganizer) {
+        return Optional.of(new DisplayAreaHelperController(mainExecutor,
+                rootDisplayAreaOrganizer));
+    }
+
+    //
+    // Splitscreen (optional feature)
+    //
+
+    @WMSingleton
+    @Provides
     static Optional<SplitScreen> provideSplitScreen(
             Optional<SplitScreenController> splitScreenController) {
         return splitScreenController.map((controller) -> controller.asSplitScreen());
     }
 
+    // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+    @BindsOptionalOf
+    @DynamicOverride
+    abstract SplitScreenController optionalSplitScreenController();
+
     @WMSingleton
     @Provides
-    static Optional<SplitScreenController> provideSplitScreenController(
-            ShellTaskOrganizer shellTaskOrganizer,
-            SyncTransactionQueue syncQueue, Context context,
-            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
-            @ShellMainThread ShellExecutor mainExecutor,
-            DisplayImeController displayImeController,
-            DisplayInsetsController displayInsetsController, Transitions transitions,
-            TransactionPool transactionPool, IconProvider iconProvider,
-            Optional<RecentTasksController> recentTasks,
-            Provider<Optional<StageTaskUnfoldController>> stageTaskUnfoldControllerProvider) {
+    static Optional<SplitScreenController> providesSplitScreenController(
+            @DynamicOverride Optional<SplitScreenController> splitscreenController,
+            Context context) {
         if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
-            return Optional.of(new SplitScreenController(shellTaskOrganizer, syncQueue, context,
-                    rootTaskDisplayAreaOrganizer, mainExecutor, displayImeController,
-                    displayInsetsController, transitions, transactionPool, iconProvider,
-                    recentTasks, stageTaskUnfoldControllerProvider));
-        } else {
-            return Optional.empty();
+            return splitscreenController;
         }
+        return Optional.empty();
     }
 
     // Legacy split (optional feature)
@@ -529,7 +531,9 @@
     @BindsOptionalOf
     abstract AppPairsController optionalAppPairs();
 
+    //
     // Starting window
+    //
 
     @WMSingleton
     @Provides
@@ -548,6 +552,23 @@
                 startingWindowTypeAlgorithm, iconProvider, pool);
     }
 
+    // Workaround for dynamic overriding with a default implementation, see {@link DynamicOverride}
+    @BindsOptionalOf
+    @DynamicOverride
+    abstract StartingWindowTypeAlgorithm optionalStartingWindowTypeAlgorithm();
+
+    @WMSingleton
+    @Provides
+    static StartingWindowTypeAlgorithm provideStartingWindowTypeAlgorithm(
+            @DynamicOverride Optional<StartingWindowTypeAlgorithm> startingWindowTypeAlgorithm
+    ) {
+        if (startingWindowTypeAlgorithm.isPresent()) {
+            return startingWindowTypeAlgorithm.get();
+        }
+        // Default to phone starting window type
+        return new PhoneStartingWindowTypeAlgorithm();
+    }
+
     //
     // Task view factory
     //
@@ -591,7 +612,7 @@
             Optional<PipTouchHandler> pipTouchHandlerOptional,
             FullscreenTaskListener fullscreenTaskListener,
             Optional<FullscreenUnfoldController> appUnfoldTransitionController,
-            Optional<Optional<FreeformTaskListener>> freeformTaskListener,
+            Optional<FreeformTaskListener> freeformTaskListener,
             Optional<RecentTasksController> recentTasksOptional,
             Transitions transitions,
             StartingWindowController startingWindow,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index ec70147..f562fd9c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -18,15 +18,22 @@
 
 import android.animation.AnimationHandler;
 import android.content.Context;
+import android.content.pm.LauncherApps;
 import android.os.Handler;
-import android.view.IWindowManager;
+import android.view.WindowManager;
 
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.launcher3.icons.IconProvider;
+import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.WindowManagerShellWrapper;
 import com.android.wm.shell.apppairs.AppPairsController;
+import com.android.wm.shell.bubbles.BubbleController;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.FloatingContentCoordinator;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
@@ -36,6 +43,7 @@
 import com.android.wm.shell.common.annotations.ChoreographerSfVsync;
 import com.android.wm.shell.common.annotations.ShellMainThread;
 import com.android.wm.shell.freeform.FreeformTaskListener;
+import com.android.wm.shell.fullscreen.FullscreenUnfoldController;
 import com.android.wm.shell.legacysplitscreen.LegacySplitScreenController;
 import com.android.wm.shell.onehanded.OneHandedController;
 import com.android.wm.shell.pip.Pip;
@@ -55,13 +63,18 @@
 import com.android.wm.shell.pip.phone.PipController;
 import com.android.wm.shell.pip.phone.PipMotionHelper;
 import com.android.wm.shell.pip.phone.PipTouchHandler;
+import com.android.wm.shell.recents.RecentTasksController;
 import com.android.wm.shell.splitscreen.SplitScreenController;
-import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
-import com.android.wm.shell.startingsurface.phone.PhoneStartingWindowTypeAlgorithm;
+import com.android.wm.shell.splitscreen.StageTaskUnfoldController;
 import com.android.wm.shell.transition.Transitions;
+import com.android.wm.shell.unfold.ShellUnfoldProgressProvider;
+import com.android.wm.shell.unfold.UnfoldBackgroundController;
 
 import java.util.Optional;
 
+import javax.inject.Provider;
+
+import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
 
@@ -77,17 +90,29 @@
 public class WMShellModule {
 
     //
-    // Internal common - Components used internally by multiple shell features
+    // Bubbles
     //
 
+    // Note: Handler needed for LauncherApps.register
     @WMSingleton
     @Provides
-    static DisplayImeController provideDisplayImeController(IWindowManager wmService,
-            DisplayController displayController, DisplayInsetsController displayInsetsController,
+    static BubbleController provideBubbleController(Context context,
+            FloatingContentCoordinator floatingContentCoordinator,
+            IStatusBarService statusBarService,
+            WindowManager windowManager,
+            WindowManagerShellWrapper windowManagerShellWrapper,
+            LauncherApps launcherApps,
+            TaskStackListenerImpl taskStackListener,
+            UiEventLogger uiEventLogger,
+            ShellTaskOrganizer organizer,
+            DisplayController displayController,
             @ShellMainThread ShellExecutor mainExecutor,
-            TransactionPool transactionPool) {
-        return new DisplayImeController(wmService, displayController, displayInsetsController,
-                mainExecutor, transactionPool);
+            @ShellMainThread Handler mainHandler,
+            SyncTransactionQueue syncQueue) {
+        return BubbleController.create(context, null /* synchronizer */,
+                floatingContentCoordinator, statusBarService, windowManager,
+                windowManagerShellWrapper, launcherApps, taskStackListener,
+                uiEventLogger, organizer, displayController, mainExecutor, mainHandler, syncQueue);
     }
 
     //
@@ -96,16 +121,55 @@
 
     @WMSingleton
     @Provides
-    static Optional<FreeformTaskListener> provideFreeformTaskListener(
-            Context context,
+    @DynamicOverride
+    static FreeformTaskListener provideFreeformTaskListener(
             SyncTransactionQueue syncQueue) {
-        return Optional.ofNullable(FreeformTaskListener.create(context, syncQueue));
+        return new FreeformTaskListener(syncQueue);
     }
 
     //
-    // Split/multiwindow
+    // One handed mode
     //
 
+
+    // Needs the shell main handler for ContentObserver callbacks
+    @WMSingleton
+    @Provides
+    @DynamicOverride
+    static OneHandedController provideOneHandedController(Context context,
+            WindowManager windowManager, DisplayController displayController,
+            DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener,
+            UiEventLogger uiEventLogger,
+            @ShellMainThread ShellExecutor mainExecutor,
+            @ShellMainThread Handler mainHandler) {
+        return OneHandedController.create(context, windowManager,
+                displayController, displayLayout, taskStackListener, uiEventLogger, mainExecutor,
+                mainHandler);
+    }
+
+    //
+    // Splitscreen
+    //
+
+    @WMSingleton
+    @Provides
+    @DynamicOverride
+    static SplitScreenController provideSplitScreenController(
+            ShellTaskOrganizer shellTaskOrganizer,
+            SyncTransactionQueue syncQueue, Context context,
+            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
+            @ShellMainThread ShellExecutor mainExecutor,
+            DisplayImeController displayImeController,
+            DisplayInsetsController displayInsetsController, Transitions transitions,
+            TransactionPool transactionPool, IconProvider iconProvider,
+            Optional<RecentTasksController> recentTasks,
+            Provider<Optional<StageTaskUnfoldController>> stageTaskUnfoldControllerProvider) {
+        return new SplitScreenController(shellTaskOrganizer, syncQueue, context,
+                rootTaskDisplayAreaOrganizer, mainExecutor, displayImeController,
+                displayInsetsController, transitions, transactionPool, iconProvider,
+                recentTasks, stageTaskUnfoldControllerProvider);
+    }
+
     @WMSingleton
     @Provides
     static LegacySplitScreenController provideLegacySplitScreen(Context context,
@@ -177,10 +241,11 @@
     static PhonePipMenuController providesPipPhoneMenuController(Context context,
             PipBoundsState pipBoundsState, PipMediaController pipMediaController,
             SystemWindows systemWindows,
+            Optional<SplitScreenController> splitScreenOptional,
             @ShellMainThread ShellExecutor mainExecutor,
             @ShellMainThread Handler mainHandler) {
         return new PhonePipMenuController(context, pipBoundsState, pipMediaController,
-                systemWindows, mainExecutor, mainHandler);
+                systemWindows, splitScreenOptional, mainExecutor, mainHandler);
     }
 
     @WMSingleton
@@ -258,12 +323,53 @@
     }
 
     //
-    // Starting Windows (Splash Screen)
+    // Unfold transition
     //
 
     @WMSingleton
     @Provides
-    static StartingWindowTypeAlgorithm provideStartingWindowTypeAlgorithm() {
-        return new PhoneStartingWindowTypeAlgorithm();
+    @DynamicOverride
+    static FullscreenUnfoldController provideFullscreenUnfoldController(
+            Context context,
+            Optional<ShellUnfoldProgressProvider> progressProvider,
+            Lazy<UnfoldBackgroundController> unfoldBackgroundController,
+            DisplayInsetsController displayInsetsController,
+            @ShellMainThread ShellExecutor mainExecutor
+    ) {
+        return new FullscreenUnfoldController(context, mainExecutor,
+                unfoldBackgroundController.get(), progressProvider.get(),
+                displayInsetsController);
+    }
+
+    @Provides
+    static Optional<StageTaskUnfoldController> provideStageTaskUnfoldController(
+            Optional<ShellUnfoldProgressProvider> progressProvider,
+            Context context,
+            TransactionPool transactionPool,
+            Lazy<UnfoldBackgroundController> unfoldBackgroundController,
+            DisplayInsetsController displayInsetsController,
+            @ShellMainThread ShellExecutor mainExecutor
+    ) {
+        return progressProvider.map(shellUnfoldTransitionProgressProvider ->
+                new StageTaskUnfoldController(
+                        context,
+                        transactionPool,
+                        shellUnfoldTransitionProgressProvider,
+                        displayInsetsController,
+                        unfoldBackgroundController.get(),
+                        mainExecutor
+                ));
+    }
+
+    @WMSingleton
+    @Provides
+    static UnfoldBackgroundController provideUnfoldBackgroundController(
+            RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer,
+            Context context
+    ) {
+        return new UnfoldBackgroundController(
+                context,
+                rootTaskDisplayAreaOrganizer
+        );
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index 0c12d6c..d2b4711 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -19,6 +19,7 @@
 import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY;
 import static android.content.ClipDescription.MIMETYPE_APPLICATION_SHORTCUT;
 import static android.content.ClipDescription.MIMETYPE_APPLICATION_TASK;
+import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.DragEvent.ACTION_DRAG_ENDED;
 import static android.view.DragEvent.ACTION_DRAG_ENTERED;
 import static android.view.DragEvent.ACTION_DRAG_EXITED;
@@ -34,13 +35,13 @@
 import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 
-import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.PixelFormat;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.Display;
 import android.view.DragEvent;
 import android.view.LayoutInflater;
 import android.view.SurfaceControl;
@@ -55,7 +56,6 @@
 import com.android.wm.shell.R;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.protolog.ShellProtoLogGroup;
-import com.android.wm.shell.splitscreen.SplitScreen;
 import com.android.wm.shell.splitscreen.SplitScreenController;
 
 import java.util.Optional;
@@ -91,6 +91,11 @@
     @Override
     public void onDisplayAdded(int displayId) {
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Display added: %d", displayId);
+        if (displayId != DEFAULT_DISPLAY) {
+            // Ignore non-default displays for now
+            return;
+        }
+
         final Context context = mDisplayController.getDisplayContext(displayId)
                 .createWindowContext(TYPE_APPLICATION_OVERLAY, null);
         final WindowManager wm = context.getSystemService(WindowManager.class);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
index 8a8d7c6..52ff21b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.freeform;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.pm.PackageManager.FEATURE_FREEFORM_WINDOW_MANAGEMENT;
 import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
 
@@ -28,7 +27,6 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.SurfaceControl;
-import android.window.WindowContainerTransaction;
 
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.ShellTaskOrganizer;
@@ -85,13 +83,6 @@
             Slog.e(TAG, "Task already vanished: #" + taskInfo.taskId);
             return;
         }
-
-        // Clears windowing mode and window bounds to let the task inherits from its new parent.
-        final WindowContainerTransaction wct = new WindowContainerTransaction();
-        wct.setBounds(taskInfo.token, null)
-                .setWindowingMode(taskInfo.token, WINDOWING_MODE_UNDEFINED);
-        mSyncQueue.queue(wct);
-
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TASK_ORG, "Freeform Task Vanished: #%d",
                 taskInfo.taskId);
         mTasks.remove(taskInfo.taskId);
@@ -141,16 +132,4 @@
                 || Settings.Global.getInt(context.getContentResolver(),
                 DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, 0) != 0;
     }
-
-    /**
-     * Creates {@link FreeformTaskListener} if freeform is enabled.
-     */
-    public static FreeformTaskListener create(Context context,
-            SyncTransactionQueue syncQueue) {
-        if (!isFreeformEnabled(context)) {
-            return null;
-        }
-
-        return new FreeformTaskListener(syncQueue);
-    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
index 80ab166..67e487d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitScreenController.java
@@ -172,6 +172,14 @@
                 };
 
         mWindowManager = new DividerWindowManager(mSystemWindows);
+
+        // No need to listen to display window container or create root tasks if the device is not
+        // using legacy split screen.
+        if (!context.getResources().getBoolean(com.android.internal.R.bool.config_useLegacySplit)) {
+            return;
+        }
+
+
         mDisplayController.addDisplayWindowListener(this);
         // Don't initialize the divider or anything until we get the default display.
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
index 3253bb0..b00182f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHanded.java
@@ -17,6 +17,7 @@
 package com.android.wm.shell.onehanded;
 
 import android.content.res.Configuration;
+import android.os.SystemProperties;
 
 import com.android.wm.shell.common.annotations.ExternalThread;
 
@@ -26,6 +27,9 @@
 @ExternalThread
 public interface OneHanded {
 
+    boolean sIsSupportOneHandedMode =  SystemProperties.getBoolean(
+            OneHandedController.SUPPORT_ONE_HANDED_MODE, false);
+
     /**
      * Returns a binder that can be passed to an external process to manipulate OneHanded.
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index 90074371..72bb655 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.onehanded;
 
-import static android.os.UserHandle.USER_CURRENT;
 import static android.os.UserHandle.myUserId;
 import static android.view.Display.DEFAULT_DISPLAY;
 
@@ -30,12 +29,10 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.om.IOverlayManager;
-import android.content.om.OverlayInfo;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.graphics.Rect;
 import android.os.Handler;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
 import android.provider.Settings;
@@ -46,7 +43,6 @@
 import android.window.WindowContainerTransaction;
 
 import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.logging.UiEventLogger;
@@ -71,12 +67,9 @@
 
     private static final String ONE_HANDED_MODE_OFFSET_PERCENTAGE =
             "persist.debug.one_handed_offset_percentage";
-    private static final String ONE_HANDED_MODE_GESTURAL_OVERLAY =
-            "com.android.internal.systemui.onehanded.gestural";
-    private static final int OVERLAY_ENABLED_DELAY_MS = 250;
     private static final int DISPLAY_AREA_READY_RETRY_MS = 10;
 
-    static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
+    public static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode";
 
     private volatile boolean mIsOneHandedEnabled;
     private volatile boolean mIsSwipeToNotificationEnabled;
@@ -198,16 +191,10 @@
     /**
      * Creates {@link OneHandedController}, returns {@code null} if the feature is not supported.
      */
-    @Nullable
     public static OneHandedController create(
             Context context, WindowManager windowManager, DisplayController displayController,
             DisplayLayout displayLayout, TaskStackListenerImpl taskStackListener,
             UiEventLogger uiEventLogger, ShellExecutor mainExecutor, Handler mainHandler) {
-        if (!SystemProperties.getBoolean(SUPPORT_ONE_HANDED_MODE, false)) {
-            Slog.w(TAG, "Device doesn't support OneHanded feature");
-            return null;
-        }
-
         OneHandedSettingsUtil settingsUtil = new OneHandedSettingsUtil();
         OneHandedAccessibilityUtil accessibilityUtil = new OneHandedAccessibilityUtil(context);
         OneHandedTimeoutHandler timeoutHandler = new OneHandedTimeoutHandler(mainExecutor);
@@ -289,7 +276,6 @@
         setupCallback();
         registerSettingObservers(mUserId);
         setupTimeoutListener();
-        setupGesturalOverlay();
         updateSettings();
 
         mAccessibilityManager = AccessibilityManager.getInstance(context);
@@ -524,11 +510,6 @@
                 : OneHandedUiEventLogger.EVENT_ONE_HANDED_SETTINGS_ENABLED_OFF);
 
         setOneHandedEnabled(enabled);
-
-        // Also checks swipe to notification settings since they all need gesture overlay.
-        setEnabledGesturalOverlay(
-                enabled || mOneHandedSettingsUtil.getSettingsSwipeToNotificationEnabled(
-                        mContext.getContentResolver(), mUserId), true /* DelayExecute */);
     }
 
     @VisibleForTesting
@@ -609,40 +590,6 @@
         }
     }
 
-    private void setupGesturalOverlay() {
-        if (!mOneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
-                mContext.getContentResolver(), mUserId)) {
-            return;
-        }
-
-        OverlayInfo info = null;
-        try {
-            mOverlayManager.setHighestPriority(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
-            info = mOverlayManager.getOverlayInfo(ONE_HANDED_MODE_GESTURAL_OVERLAY, USER_CURRENT);
-        } catch (RemoteException e) { /* Do nothing */ }
-
-        if (info != null && !info.isEnabled()) {
-            // Enable the default gestural one handed overlay.
-            setEnabledGesturalOverlay(true /* enabled */, false /* delayExecute */);
-        }
-    }
-
-    @VisibleForTesting
-    private void setEnabledGesturalOverlay(boolean enabled, boolean delayExecute) {
-        if (mState.isTransitioning() || delayExecute) {
-            // Enabled overlay package may affect the current animation(e.g:Settings switch),
-            // so we delay 250ms to enabled overlay after switch animation finish, only delay once.
-            mMainExecutor.executeDelayed(() -> setEnabledGesturalOverlay(enabled, false),
-                    OVERLAY_ENABLED_DELAY_MS);
-            return;
-        }
-        try {
-            mOverlayManager.setEnabled(ONE_HANDED_MODE_GESTURAL_OVERLAY, enabled, USER_CURRENT);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
     @VisibleForTesting
     void setLockedDisabled(boolean locked, boolean enabled) {
         final boolean isFeatureEnabled = mIsOneHandedEnabled || mIsSwipeToNotificationEnabled;
@@ -721,19 +668,6 @@
         }
 
         mOneHandedSettingsUtil.dump(pw, innerPrefix, mContext.getContentResolver(), mUserId);
-
-        if (mOverlayManager != null) {
-            OverlayInfo info = null;
-            try {
-                info = mOverlayManager.getOverlayInfo(ONE_HANDED_MODE_GESTURAL_OVERLAY,
-                        USER_CURRENT);
-            } catch (RemoteException e) { /* Do nothing */ }
-
-            if (info != null && !info.isEnabled()) {
-                pw.print(innerPrefix + "OverlayInfo=");
-                pw.println(info);
-            }
-        }
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index 05111a3..9575b0a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -594,10 +594,10 @@
                         getSurfaceTransactionHelper().scaleAndCrop(tx, leash,
                                 initialSourceValue, bounds, insets);
                         if (shouldApplyCornerRadius()) {
-                            final Rect destinationBounds = new Rect(bounds);
-                            destinationBounds.inset(insets);
+                            final Rect sourceBounds = new Rect(initialContainerRect);
+                            sourceBounds.inset(insets);
                             getSurfaceTransactionHelper().round(tx, leash,
-                                    initialContainerRect, destinationBounds);
+                                    sourceBounds, bounds);
                         }
                     }
                     if (!handlePipTransaction(leash, tx, bounds)) {
@@ -641,11 +641,13 @@
                             y = fraction * (end.bottom - start.top) + start.top;
                         }
                     }
+                    final Rect sourceBounds = new Rect(initialContainerRect);
+                    sourceBounds.inset(insets);
                     getSurfaceTransactionHelper()
                             .rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds,
                                     insets, degree, x, y, isOutPipDirection,
                                     rotationDelta == ROTATION_270 /* clockwise */)
-                            .round(tx, leash, initialContainerRect, bounds);
+                            .round(tx, leash, sourceBounds, bounds);
                     tx.apply();
                 }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java
index 8d9ad4d..caa1f01 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipMenuController.java
@@ -90,6 +90,11 @@
     default void updateMenuBounds(Rect destinationBounds) {}
 
     /**
+     * Update when the current focused task changes.
+     */
+    default void onFocusTaskChanged(RunningTaskInfo taskInfo) {}
+
+    /**
      * Returns a default LayoutParams for the PIP Menu.
      * @param width the PIP stack width.
      * @param height the PIP stack height.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 6cc5f09..c2ebc30 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -98,7 +98,7 @@
  * see also {@link PipMotionHelper}.
  */
 public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
-        DisplayController.OnDisplaysChangedListener {
+        DisplayController.OnDisplaysChangedListener, ShellTaskOrganizer.FocusListener {
     private static final String TAG = PipTaskOrganizer.class.getSimpleName();
     private static final boolean DEBUG = false;
     /**
@@ -286,6 +286,7 @@
         mMainExecutor.execute(() -> {
             mTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_PIP);
         });
+        mTaskOrganizer.addFocusListener(this);
         mPipTransitionController.setPipOrganizer(this);
         displayController.addDisplayWindowListener(this);
     }
@@ -772,6 +773,11 @@
     }
 
     @Override
+    public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
+        mPipMenuController.onFocusTaskChanged(taskInfo);
+    }
+
+    @Override
     public boolean supportSizeCompatUI() {
         // PIP doesn't support size compat.
         return false;
@@ -1282,6 +1288,9 @@
     }
 
     private boolean isPipTopLeft() {
+        if (!mSplitScreenOptional.isPresent()) {
+            return false;
+        }
         final Rect topLeft = new Rect();
         final Rect bottomRight = new Rect();
         mSplitScreenOptional.get().getStageBounds(topLeft, bottomRight);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
index 5687f4d..eb512af 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipMenuController.java
@@ -19,6 +19,7 @@
 import static android.view.WindowManager.SHELL_ROOT_LAYER_PIP;
 
 import android.annotation.Nullable;
+import android.app.ActivityManager;
 import android.app.RemoteAction;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
@@ -43,10 +44,12 @@
 import com.android.wm.shell.pip.PipMediaController;
 import com.android.wm.shell.pip.PipMediaController.ActionListener;
 import com.android.wm.shell.pip.PipMenuController;
+import com.android.wm.shell.splitscreen.SplitScreenController;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 
 /**
  * Manages the PiP menu view which can show menu options or a scrim.
@@ -114,6 +117,7 @@
 
     private final ArrayList<Listener> mListeners = new ArrayList<>();
     private final SystemWindows mSystemWindows;
+    private final Optional<SplitScreenController> mSplitScreenController;
     private ParceledListSlice<RemoteAction> mAppActions;
     private ParceledListSlice<RemoteAction> mMediaActions;
     private SyncRtSurfaceTransactionApplier mApplier;
@@ -145,6 +149,7 @@
 
     public PhonePipMenuController(Context context, PipBoundsState pipBoundsState,
             PipMediaController mediaController, SystemWindows systemWindows,
+            Optional<SplitScreenController> splitScreenOptional,
             ShellExecutor mainExecutor, Handler mainHandler) {
         mContext = context;
         mPipBoundsState = pipBoundsState;
@@ -152,6 +157,7 @@
         mSystemWindows = systemWindows;
         mMainExecutor = mainExecutor;
         mMainHandler = mainHandler;
+        mSplitScreenController = splitScreenOptional;
     }
 
     public boolean isMenuVisible() {
@@ -180,7 +186,8 @@
         if (mPipMenuView != null) {
             detachPipMenuView();
         }
-        mPipMenuView = new PipMenuView(mContext, this, mMainExecutor, mMainHandler);
+        mPipMenuView = new PipMenuView(mContext, this, mMainExecutor, mMainHandler,
+                mSplitScreenController);
         mSystemWindows.addView(mPipMenuView,
                 getPipMenuLayoutParams(MENU_WINDOW_TITLE, 0 /* width */, 0 /* height */),
                 0, SHELL_ROOT_LAYER_PIP);
@@ -209,6 +216,13 @@
         updateMenuLayout(destinationBounds);
     }
 
+    @Override
+    public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
+        if (mPipMenuView != null) {
+            mPipMenuView.onFocusTaskChanged(taskInfo);
+        }
+    }
+
     /**
      * Tries to grab a surface control from {@link PipMenuView}. If this isn't available for some
      * reason (ie. the window isn't ready yet, thus {@link android.view.ViewRootImpl} is
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index f25cff7..79e3444 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -88,7 +88,6 @@
 import com.android.wm.shell.transition.Transitions;
 
 import java.io.PrintWriter;
-import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Consumer;
 
@@ -469,7 +468,7 @@
     }
 
     private void onDisplayChanged(DisplayLayout layout, boolean saveRestoreSnapFraction) {
-        if (Objects.equals(layout, mPipBoundsState.getDisplayLayout())) {
+        if (mPipBoundsState.getDisplayLayout().isSameGeometry(layout)) {
             return;
         }
         Runnable updateDisplayLayout = () -> {
@@ -491,25 +490,12 @@
         if (mPipTaskOrganizer.isInPip() && saveRestoreSnapFraction) {
             // Calculate the snap fraction of the current stack along the old movement bounds
             final PipSnapAlgorithm pipSnapAlgorithm = mPipBoundsAlgorithm.getSnapAlgorithm();
-            final float snapFraction = pipSnapAlgorithm.getSnapFraction(mPipBoundsState.getBounds(),
-                    mPipBoundsAlgorithm.getMovementBounds(mPipBoundsState.getBounds()),
+            final Rect postChangeStackBounds = new Rect(mPipBoundsState.getBounds());
+            final float snapFraction = pipSnapAlgorithm.getSnapFraction(postChangeStackBounds,
+                    mPipBoundsAlgorithm.getMovementBounds(postChangeStackBounds),
                     mPipBoundsState.getStashedState());
 
             updateDisplayLayout.run();
-            final Rect postChangeStackBounds;
-            if (mPipBoundsState.getBounds() != null
-                    && (mPipBoundsState.getBounds().width() > mPipBoundsState.getMaxSize().x
-                    || mPipBoundsState.getBounds().height() > mPipBoundsState.getMaxSize().y)) {
-                postChangeStackBounds = new Rect(0, 0, mPipBoundsState.getMaxSize().x,
-                        mPipBoundsState.getMaxSize().y);
-            } else if (mPipBoundsState.getBounds() != null
-                    && (mPipBoundsState.getBounds().width() < mPipBoundsState.getMinSize().x
-                    || mPipBoundsState.getBounds().height() < mPipBoundsState.getMinSize().y)) {
-                postChangeStackBounds = new Rect(0, 0, mPipBoundsState.getMinSize().x,
-                        mPipBoundsState.getMinSize().y);
-            } else {
-                postChangeStackBounds = new Rect(mPipBoundsState.getBounds());
-            }
 
             // Calculate the stack bounds in the new orientation based on same fraction along the
             // rotated movement bounds.
@@ -521,7 +507,7 @@
                     mPipBoundsState.getDisplayBounds(),
                     mPipBoundsState.getDisplayLayout().stableInsets());
 
-            mTouchHandler.getMotionHelper().animateResizedBounds(postChangeStackBounds);
+            mTouchHandler.getMotionHelper().movePip(postChangeStackBounds);
         } else {
             updateDisplayLayout.run();
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
index b209699..82e8273 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMenuView.java
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.pip.phone;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.provider.Settings.ACTION_PICTURE_IN_PICTURE_SETTINGS;
@@ -32,8 +33,10 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.annotation.IntDef;
+import android.app.ActivityManager;
 import android.app.PendingIntent.CanceledException;
 import android.app.RemoteAction;
+import android.app.WindowConfiguration;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -61,11 +64,13 @@
 import com.android.wm.shell.animation.Interpolators;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.pip.PipUtils;
+import com.android.wm.shell.splitscreen.SplitScreenController;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Optional;
 
 /**
  * Translucent window that gets started on top of a task in PIP to allow the user to control it.
@@ -105,6 +110,7 @@
     private boolean mAllowMenuTimeout = true;
     private boolean mAllowTouches = true;
     private int mDismissFadeOutDurationMs;
+    private boolean mFocusedTaskAllowSplitScreen;
 
     private final List<RemoteAction> mActions = new ArrayList<>();
 
@@ -116,6 +122,7 @@
 
     private AnimatorSet mMenuContainerAnimator;
     private PhonePipMenuController mController;
+    private Optional<SplitScreenController> mSplitScreenControllerOptional;
 
     private ValueAnimator.AnimatorUpdateListener mMenuBgUpdateListener =
             new ValueAnimator.AnimatorUpdateListener() {
@@ -144,12 +151,14 @@
     protected PipMenuIconsAlgorithm mPipMenuIconsAlgorithm;
 
     public PipMenuView(Context context, PhonePipMenuController controller,
-            ShellExecutor mainExecutor, Handler mainHandler) {
+            ShellExecutor mainExecutor, Handler mainHandler,
+            Optional<SplitScreenController> splitScreenController) {
         super(context, null, 0);
         mContext = context;
         mController = controller;
         mMainExecutor = mainExecutor;
         mMainHandler = mainHandler;
+        mSplitScreenControllerOptional = splitScreenController;
 
         mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
         inflate(context, R.layout.pip_menu, this);
@@ -255,6 +264,15 @@
         return super.dispatchGenericMotionEvent(event);
     }
 
+    public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
+        final boolean isSplitScreen = mSplitScreenControllerOptional.isPresent()
+                && mSplitScreenControllerOptional.get().isTaskInSplitScreen(taskInfo.taskId);
+        mFocusedTaskAllowSplitScreen = isSplitScreen
+                || (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
+                && taskInfo.supportsSplitScreenMultiWindow
+                && taskInfo.topActivityType != WindowConfiguration.ACTIVITY_TYPE_HOME);
+    }
+
     void showMenu(int menuState, Rect stackBounds, boolean allowMenuTimeout,
             boolean resizeMenuOnShow, boolean withDelay, boolean showResizeHandle) {
         mAllowMenuTimeout = allowMenuTimeout;
@@ -278,7 +296,8 @@
             ObjectAnimator dismissAnim = ObjectAnimator.ofFloat(mDismissButton, View.ALPHA,
                     mDismissButton.getAlpha(), 1f);
             ObjectAnimator enterSplitAnim = ObjectAnimator.ofFloat(mEnterSplitButton, View.ALPHA,
-                    mEnterSplitButton.getAlpha(), ENABLE_ENTER_SPLIT ? 1f : 0f);
+                    mEnterSplitButton.getAlpha(),
+                    ENABLE_ENTER_SPLIT && mFocusedTaskAllowSplitScreen ? 1f : 0f);
             if (menuState == MENU_STATE_FULL) {
                 mMenuContainerAnimator.playTogether(menuAnim, settingsAnim, dismissAnim,
                         enterSplitAnim);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
index c634b7f..96fd59f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipMotionHelper.java
@@ -69,7 +69,6 @@
     private static final int UNSTASH_DURATION = 250;
     private static final int LEAVE_PIP_DURATION = 300;
     private static final int SHIFT_DURATION = 300;
-    private static final int ANIMATE_PIP_RESIZE_ANIMATION = 250;
 
     /** Friction to use for PIP when it moves via physics fling animations. */
     private static final float DEFAULT_FRICTION = 1.9f;
@@ -549,14 +548,6 @@
     }
 
     /**
-     * Animates the PiP from an old bound to a new bound. This is mostly used when display
-     * has changed and PiP bounds needs to be changed.
-     */
-    void animateResizedBounds(Rect newBounds) {
-        resizeAndAnimatePipUnchecked(newBounds, ANIMATE_PIP_RESIZE_ANIMATION);
-    }
-
-    /**
      * Animates the PiP to offset it from the IME or shelf.
      */
     void animateToOffset(Rect originalBounds, int offset) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
index 00083d9..83390a5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
@@ -57,7 +57,7 @@
 public class TvPipController implements PipTransitionController.PipTransitionCallback,
         TvPipMenuController.Delegate, TvPipNotificationController.Delegate {
     private static final String TAG = "TvPipController";
-    static final boolean DEBUG = true;
+    static final boolean DEBUG = false;
 
     private static final int NONEXISTENT_TASK_ID = -1;
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
index 963a3dc..79c1df2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java
@@ -32,6 +32,8 @@
             Consts.TAG_WM_SHELL),
     WM_SHELL_DRAG_AND_DROP(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
             Consts.TAG_WM_SHELL),
+    WM_SHELL_STARTING_WINDOW(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false,
+            Consts.TAG_WM_STARTING_WINDOW),
     TEST_GROUP(true, true, false, "WindowManagerShellProtoLogTest");
 
     private final boolean mEnabled;
@@ -91,6 +93,7 @@
 
     private static class Consts {
         private static final String TAG_WM_SHELL = "WindowManagerShell";
+        private static final String TAG_WM_STARTING_WINDOW = "ShellStartingWindow";
 
         private static final boolean ENABLE_DEBUG = true;
         private static final boolean ENABLE_LOG_TO_PROTO_DEBUG = true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index 7cf3baf..a006f30 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -111,6 +111,11 @@
         if (taskId1 == taskId2) {
             return;
         }
+        if (mSplitTasks.get(taskId1, INVALID_TASK_ID) == taskId2
+                && mTaskSplitBoundsMap.get(taskId1).equals(splitBounds)) {
+            // If the two tasks are already paired and the bounds are the same, then skip updating
+            return;
+        }
         // Remove any previous pairs
         removeSplitPair(taskId1);
         removeSplitPair(taskId2);
@@ -121,6 +126,7 @@
         mSplitTasks.put(taskId2, taskId1);
         mTaskSplitBoundsMap.put(taskId1, splitBounds);
         mTaskSplitBoundsMap.put(taskId2, splitBounds);
+        notifyRecentTasksChanged();
     }
 
     /**
@@ -133,6 +139,7 @@
             mSplitTasks.delete(pairedTaskId);
             mTaskSplitBoundsMap.remove(taskId);
             mTaskSplitBoundsMap.remove(pairedTaskId);
+            notifyRecentTasksChanged();
         }
     }
 
@@ -217,7 +224,7 @@
             }
 
             final int pairedTaskId = mSplitTasks.get(taskInfo.taskId);
-            if (pairedTaskId != INVALID_TASK_ID) {
+            if (pairedTaskId != INVALID_TASK_ID && rawMapping.contains(pairedTaskId)) {
                 final ActivityManager.RecentTaskInfo pairedTaskInfo = rawMapping.get(pairedTaskId);
                 rawMapping.remove(pairedTaskId);
                 recentTasks.add(new GroupedRecentTaskInfo(taskInfo, pairedTaskInfo,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUI.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUI.java
new file mode 100644
index 0000000..a703114
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUI.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2021 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.wm.shell.sizecompatui;
+
+import com.android.wm.shell.common.annotations.ExternalThread;
+
+/**
+ * Interface to engage size compat UI.
+ */
+@ExternalThread
+public interface SizeCompatUI {
+    /**
+     * Called when the keyguard occluded state changes. Removes all size compat UIs if the
+     * keyguard is now occluded.
+     * @param occluded indicates if the keyguard is now occluded.
+     */
+    void onKeyguardOccludedChanged(boolean occluded);
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
index 04d974a..e06070a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
@@ -35,13 +35,16 @@
 import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener;
 import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.common.annotations.ExternalThread;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
 import java.util.function.Consumer;
+import java.util.function.Predicate;
 
 /**
  * Controls to show/update restart-activity buttons on Tasks based on whether the foreground
@@ -78,26 +81,37 @@
     private final DisplayInsetsController mDisplayInsetsController;
     private final DisplayImeController mImeController;
     private final SyncTransactionQueue mSyncQueue;
+    private final ShellExecutor mMainExecutor;
+    private final SizeCompatUIImpl mImpl = new SizeCompatUIImpl();
 
     private SizeCompatUICallback mCallback;
 
     /** Only show once automatically in the process life. */
     private boolean mHasShownHint;
+    /** Indicates if the keyguard is currently occluded, in which case size compat UIs shouldn't
+     * be shown. */
+    private boolean mKeyguardOccluded;
 
     public SizeCompatUIController(Context context,
             DisplayController displayController,
             DisplayInsetsController displayInsetsController,
             DisplayImeController imeController,
-            SyncTransactionQueue syncQueue) {
+            SyncTransactionQueue syncQueue,
+            ShellExecutor mainExecutor) {
         mContext = context;
         mDisplayController = displayController;
         mDisplayInsetsController = displayInsetsController;
         mImeController = imeController;
         mSyncQueue = syncQueue;
+        mMainExecutor = mainExecutor;
         mDisplayController.addDisplayWindowListener(this);
         mImeController.addPositionProcessor(this);
     }
 
+    public SizeCompatUI asSizeCompatUI() {
+        return mImpl;
+    }
+
     /** Sets the callback for UI interactions. */
     public void setSizeCompatUICallback(SizeCompatUICallback callback) {
         mCallback = callback;
@@ -106,6 +120,7 @@
     /**
      * Called when the Task info changed. Creates and updates the size compat UI if there is an
      * activity in size compat, or removes the UI if there is no size compat activity.
+     *
      * @param displayId display the task and activity are in.
      * @param taskId task the activity is in.
      * @param taskConfig task config to place the size compat UI with.
@@ -180,7 +195,19 @@
         }
 
         // Hide the size compat UIs when input method is showing.
-        forAllLayoutsOnDisplay(displayId, layout -> layout.updateImeVisibility(isShowing));
+        forAllLayoutsOnDisplay(displayId,
+                layout -> layout.updateVisibility(showOnDisplay(displayId)));
+    }
+
+    @VisibleForTesting
+    void onKeyguardOccludedChanged(boolean occluded) {
+        mKeyguardOccluded = occluded;
+        // Hide the size compat UIs when keyguard is occluded.
+        forAllLayouts(layout -> layout.updateVisibility(showOnDisplay(layout.getDisplayId())));
+    }
+
+    private boolean showOnDisplay(int displayId) {
+        return !mKeyguardOccluded && !isImeShowingOnDisplay(displayId);
     }
 
     private boolean isImeShowingOnDisplay(int displayId) {
@@ -198,7 +225,7 @@
         final SizeCompatUILayout layout = createLayout(context, displayId, taskId, taskConfig,
                 taskListener);
         mActiveLayouts.put(taskId, layout);
-        layout.createSizeCompatButton(isImeShowingOnDisplay(displayId));
+        layout.createSizeCompatButton(showOnDisplay(displayId));
     }
 
     @VisibleForTesting
@@ -218,8 +245,7 @@
         if (layout == null) {
             return;
         }
-        layout.updateSizeCompatInfo(taskConfig, taskListener,
-                isImeShowingOnDisplay(layout.getDisplayId()));
+        layout.updateSizeCompatInfo(taskConfig, taskListener, showOnDisplay(layout.getDisplayId()));
     }
 
     private void removeLayout(int taskId) {
@@ -250,15 +276,37 @@
     }
 
     private void forAllLayoutsOnDisplay(int displayId, Consumer<SizeCompatUILayout> callback) {
+        forAllLayouts(layout -> layout.getDisplayId() == displayId, callback);
+    }
+
+    private void forAllLayouts(Consumer<SizeCompatUILayout> callback) {
+        forAllLayouts(layout -> true, callback);
+    }
+
+    private void forAllLayouts(Predicate<SizeCompatUILayout> condition,
+            Consumer<SizeCompatUILayout> callback) {
         for (int i = 0; i < mActiveLayouts.size(); i++) {
             final int taskId = mActiveLayouts.keyAt(i);
             final SizeCompatUILayout layout = mActiveLayouts.get(taskId);
-            if (layout != null && layout.getDisplayId() == displayId) {
+            if (layout != null && condition.test(layout)) {
                 callback.accept(layout);
             }
         }
     }
 
+    /**
+     * The interface for calls from outside the Shell, within the host process.
+     */
+    @ExternalThread
+    private class SizeCompatUIImpl implements SizeCompatUI {
+        @Override
+        public void onKeyguardOccludedChanged(boolean occluded) {
+            mMainExecutor.execute(() -> {
+                SizeCompatUIController.this.onKeyguardOccludedChanged(occluded);
+            });
+        }
+    }
+
     /** An implementation of {@link OnInsetsChangedListener} for a given display id. */
     private class PerDisplayOnInsetsChangedListener implements OnInsetsChangedListener {
         final int mDisplayId;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
index 1a2c94f..c35b89a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
@@ -103,9 +103,9 @@
     }
 
     /** Creates the activity restart button window. */
-    void createSizeCompatButton(boolean isImeShowing) {
-        if (isImeShowing || mButton != null) {
-            // When ime is showing, wait until ime is dismiss to create UI.
+    void createSizeCompatButton(boolean show) {
+        if (!show || mButton != null) {
+            // Wait until button should be visible.
             return;
         }
         mButton = mButtonWindowManager.createSizeCompatButton();
@@ -154,7 +154,7 @@
 
     /** Called when size compat info changed. */
     void updateSizeCompatInfo(Configuration taskConfig,
-            ShellTaskOrganizer.TaskListener taskListener, boolean isImeShowing) {
+            ShellTaskOrganizer.TaskListener taskListener, boolean show) {
         final Configuration prevTaskConfig = mTaskConfig;
         final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener;
         mTaskConfig = taskConfig;
@@ -170,7 +170,7 @@
         if (mButton == null || prevTaskListener != taskListener) {
             // TaskListener changed, recreate the button for new surface parent.
             release();
-            createSizeCompatButton(isImeShowing);
+            createSizeCompatButton(show);
             return;
         }
 
@@ -204,16 +204,16 @@
         }
     }
 
-    /** Called when IME visibility changed. */
-    void updateImeVisibility(boolean isImeShowing) {
+    /** Called when the visibility of the UI should change. */
+    void updateVisibility(boolean show) {
         if (mButton == null) {
-            // Button may not be created because ime is previous showing.
-            createSizeCompatButton(isImeShowing);
+            // Button may not have been created because it was hidden previously.
+            createSizeCompatButton(show);
             return;
         }
 
         // Hide size compat UIs when IME is showing.
-        final int newVisibility = isImeShowing ? View.GONE : View.VISIBLE;
+        final int newVisibility = show ? View.VISIBLE : View.GONE;
         if (mButton.getVisibility() != newVisibility) {
             mButton.setVisibility(newVisibility);
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
index 3d3a630..4a99097 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl
@@ -83,14 +83,15 @@
      * Starts tasks simultaneously in one transition.
      */
     oneway void startTasks(int mainTaskId, in Bundle mainOptions, int sideTaskId,
-            in Bundle sideOptions, int sidePosition, in RemoteTransition remoteTransition) = 10;
+            in Bundle sideOptions, int sidePosition, float splitRatio,
+            in RemoteTransition remoteTransition) = 10;
 
     /**
      * Version of startTasks using legacy transition system.
      */
      oneway void startTasksWithLegacyTransition(int mainTaskId, in Bundle mainOptions,
                             int sideTaskId, in Bundle sideOptions, int sidePosition,
-                            in RemoteAnimationAdapter adapter) = 11;
+                            float splitRatio, in RemoteAnimationAdapter adapter) = 11;
 
     /**
      * Blocking call that notifies and gets additional split-screen targets when entering
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
index f8c0304..1ba1d22 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
@@ -50,10 +50,6 @@
         wct.setBounds(rootToken, rootBounds).reorder(rootToken, true /* onTop */);
     }
 
-    void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) {
-        wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/);
-    }
-
     boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) {
         // No matter if the root task is empty or not, moving the root to bottom because it no
         // longer preserves visible child task.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index e86462f..02edaa0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -87,6 +87,12 @@
      */
     void onKeyguardVisibilityChanged(boolean showing);
 
+    /** Called when device waking up finished. */
+    void onFinishedWakingUp();
+
+    /** Called when device going to sleep finished. */
+    void onFinishedGoingToSleep();
+
     /** Get a string representation of a stage type */
     static String stageTypeToString(@StageType int stage) {
         switch (stage) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 7457be2..262a9a1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -24,6 +24,8 @@
 import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
 import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
+import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
 
 import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
@@ -130,19 +132,6 @@
 
     private StageCoordinator mStageCoordinator;
 
-    // TODO(b/205019015): Remove after we clean up downstream modules
-    public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
-            SyncTransactionQueue syncQueue, Context context,
-            RootTaskDisplayAreaOrganizer rootTDAOrganizer,
-            ShellExecutor mainExecutor, DisplayImeController displayImeController,
-            DisplayInsetsController displayInsetsController,
-            Transitions transitions, TransactionPool transactionPool, IconProvider iconProvider,
-            Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) {
-        this(shellTaskOrganizer, syncQueue, context, rootTDAOrganizer, mainExecutor,
-                displayImeController, displayInsetsController, transitions, transactionPool,
-                iconProvider, Optional.empty(), unfoldControllerProvider);
-    }
-
     public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
             SyncTransactionQueue syncQueue, Context context,
             RootTaskDisplayAreaOrganizer rootTDAOrganizer,
@@ -194,31 +183,23 @@
         return mStageCoordinator.isSplitScreenVisible();
     }
 
+    public boolean isTaskInSplitScreen(int taskId) {
+        return isSplitScreenVisible()
+                && mStageCoordinator.getStageOfTask(taskId) != STAGE_TYPE_UNDEFINED;
+    }
+
     public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition) {
+        return moveToStage(taskId, STAGE_TYPE_SIDE, sideStagePosition,
+                new WindowContainerTransaction());
+    }
+
+    private boolean moveToStage(int taskId, @SplitScreen.StageType int stageType,
+            @SplitPosition int stagePosition, WindowContainerTransaction wct) {
         final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
         if (task == null) {
             throw new IllegalArgumentException("Unknown taskId" + taskId);
         }
-        return moveToSideStage(task, sideStagePosition);
-    }
-
-    public boolean moveToSideStage(int taskId, @SplitPosition int sideStagePosition,
-            WindowContainerTransaction wct) {
-        final ActivityManager.RunningTaskInfo task = mTaskOrganizer.getRunningTaskInfo(taskId);
-        if (task == null) {
-            throw new IllegalArgumentException("Unknown taskId" + taskId);
-        }
-        return moveToSideStage(task, sideStagePosition, wct);
-    }
-
-    public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
-            @SplitPosition int sideStagePosition) {
-        return mStageCoordinator.moveToSideStage(task, sideStagePosition);
-    }
-
-    public boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
-            @SplitPosition int sideStagePosition, WindowContainerTransaction wct) {
-        return mStageCoordinator.moveToSideStage(task, sideStagePosition, wct);
+        return mStageCoordinator.moveToStage(task, stageType, stagePosition, wct);
     }
 
     public boolean removeFromSideStage(int taskId) {
@@ -234,13 +215,14 @@
     }
 
     public void enterSplitScreen(int taskId, boolean leftOrTop) {
-        moveToSideStage(taskId,
-                leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT);
+        enterSplitScreen(taskId, leftOrTop, new WindowContainerTransaction());
     }
 
     public void enterSplitScreen(int taskId, boolean leftOrTop, WindowContainerTransaction wct) {
-        moveToSideStage(taskId,
-                leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT, wct);
+        final int stageType = isSplitScreenVisible() ? STAGE_TYPE_UNDEFINED : STAGE_TYPE_SIDE;
+        final int stagePosition =
+                leftOrTop ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT;
+        moveToStage(taskId, stageType, stagePosition, wct);
     }
 
     public void exitSplitScreen(int toTopTaskId, @ExitReason int exitReason) {
@@ -255,6 +237,14 @@
         mStageCoordinator.onKeyguardVisibilityChanged(showing);
     }
 
+    public void onFinishedWakingUp() {
+        mStageCoordinator.onFinishedWakingUp();
+    }
+
+    public void onFinishedGoingToSleep() {
+        mStageCoordinator.onFinishedGoingToSleep();
+    }
+
     public void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
         mStageCoordinator.exitSplitScreenOnHide(exitSplitScreenOnHide);
     }
@@ -514,6 +504,20 @@
                 SplitScreenController.this.onKeyguardVisibilityChanged(showing);
             });
         }
+
+        @Override
+        public void onFinishedWakingUp() {
+            mMainExecutor.execute(() -> {
+                SplitScreenController.this.onFinishedWakingUp();
+            });
+        }
+
+        @Override
+        public void onFinishedGoingToSleep() {
+            mMainExecutor.execute(() -> {
+                SplitScreenController.this.onFinishedGoingToSleep();
+            });
+        }
     }
 
     /**
@@ -606,21 +610,21 @@
         @Override
         public void startTasksWithLegacyTransition(int mainTaskId, @Nullable Bundle mainOptions,
                 int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition,
-                RemoteAnimationAdapter adapter) {
+                float splitRatio, RemoteAnimationAdapter adapter) {
             executeRemoteCallWithTaskPermission(mController, "startTasks",
                     (controller) -> controller.mStageCoordinator.startTasksWithLegacyTransition(
                             mainTaskId, mainOptions, sideTaskId, sideOptions, sidePosition,
-                            adapter));
+                            splitRatio, adapter));
         }
 
         @Override
         public void startTasks(int mainTaskId, @Nullable Bundle mainOptions,
                 int sideTaskId, @Nullable Bundle sideOptions,
-                @SplitPosition int sidePosition,
+                @SplitPosition int sidePosition, float splitRatio,
                 @Nullable RemoteTransition remoteTransition) {
             executeRemoteCallWithTaskPermission(mController, "startTasks",
                     (controller) -> controller.mStageCoordinator.startTasks(mainTaskId, mainOptions,
-                            sideTaskId, sideOptions, sidePosition, remoteTransition));
+                            sideTaskId, sideOptions, sidePosition, splitRatio, remoteTransition));
         }
 
         @Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 050d255..a5579ae 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -78,7 +78,6 @@
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
-import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.InstanceId;
 import com.android.internal.protolog.common.ProtoLog;
@@ -156,10 +155,7 @@
     private boolean mShouldUpdateRecents;
     private boolean mExitSplitScreenOnHide;
     private boolean mKeyguardOccluded;
-
-    // TODO(b/187041611): remove this flag after totally deprecated legacy split
-    /** Whether the device is supporting legacy split or not. */
-    private boolean mUseLegacySplit;
+    private boolean mDeviceSleep;
 
     @SplitScreen.StageType
     private int mDismissTop = NO_DISMISS;
@@ -278,18 +274,42 @@
         return mSideStageListener.mVisible && mMainStageListener.mVisible;
     }
 
-    boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
-            @SplitPosition int sideStagePosition) {
-        final WindowContainerTransaction wct = new WindowContainerTransaction();
-        return moveToSideStage(task, sideStagePosition, wct);
+    @SplitScreen.StageType
+    int getStageOfTask(int taskId) {
+        if (mMainStage.containsTask(taskId)) {
+            return STAGE_TYPE_MAIN;
+        } else if (mSideStage.containsTask(taskId)) {
+            return STAGE_TYPE_SIDE;
+        }
+
+        return STAGE_TYPE_UNDEFINED;
     }
 
-    boolean moveToSideStage(ActivityManager.RunningTaskInfo task,
-            @SplitPosition int sideStagePosition, WindowContainerTransaction wct) {
-        final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+    boolean moveToStage(ActivityManager.RunningTaskInfo task, @SplitScreen.StageType int stageType,
+            @SplitPosition int stagePosition, WindowContainerTransaction wct) {
+        StageTaskListener targetStage;
+        int sideStagePosition;
+        if (stageType == STAGE_TYPE_MAIN) {
+            targetStage = mMainStage;
+            sideStagePosition = SplitLayout.reversePosition(stagePosition);
+        } else if (stageType == STAGE_TYPE_SIDE) {
+            targetStage = mSideStage;
+            sideStagePosition = stagePosition;
+        } else {
+            if (mMainStage.isActive()) {
+                // If the split screen is activated, retrieves target stage based on position.
+                targetStage = stagePosition == mSideStagePosition ? mSideStage : mMainStage;
+                sideStagePosition = mSideStagePosition;
+            } else {
+                targetStage = mSideStage;
+                sideStagePosition = stagePosition;
+            }
+        }
+
         setSideStagePosition(sideStagePosition, wct);
-        mSideStage.evictAllChildren(evictWct);
-        mSideStage.addTask(task, wct);
+        final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+        targetStage.evictAllChildren(evictWct);
+        targetStage.addTask(task, wct);
         if (!evictWct.isEmpty()) {
             wct.merge(evictWct, true /* transfer */);
         }
@@ -313,7 +333,7 @@
 
     /** Starts 2 tasks in one transition. */
     void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId,
-            @Nullable Bundle sideOptions, @SplitPosition int sidePosition,
+            @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio,
             @Nullable RemoteTransition remoteTransition) {
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         mainOptions = mainOptions != null ? mainOptions : new Bundle();
@@ -325,6 +345,7 @@
         mMainStage.activate(getMainStageBounds(), wct, false /* reparent */);
         mSideStage.setBounds(getSideStageBounds(), wct);
 
+        mSplitLayout.setDivideRatio(splitRatio);
         // Make sure the launch options will put tasks in the corresponding split roots
         addActivityOptions(mainOptions, mMainStage);
         addActivityOptions(sideOptions, mSideStage);
@@ -340,7 +361,7 @@
     /** Starts 2 tasks in one legacy transition. */
     void startTasksWithLegacyTransition(int mainTaskId, @Nullable Bundle mainOptions,
             int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition,
-            RemoteAnimationAdapter adapter) {
+            float splitRatio, RemoteAnimationAdapter adapter) {
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         // Need to add another wrapper here in shell so that we can inject the divider bar
         // and also manage the process elevation via setRunningRemote
@@ -395,6 +416,7 @@
         sideOptions = sideOptions != null ? sideOptions : new Bundle();
         setSideStagePosition(sidePosition, wct);
 
+        mSplitLayout.setDivideRatio(splitRatio);
         // Build a request WCT that will launch both apps such that task 0 is on the main stage
         // while task 1 is on the side stage.
         mMainStage.activate(getMainStageBounds(), wct, false /* reparent */);
@@ -468,9 +490,7 @@
             case STAGE_TYPE_MAIN: {
                 if (position != SPLIT_POSITION_UNDEFINED) {
                     // Set the side stage opposite of what we want to the main stage.
-                    final int sideStagePosition = position == SPLIT_POSITION_TOP_OR_LEFT
-                            ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
-                    setSideStagePosition(sideStagePosition, wct);
+                    setSideStagePosition(SplitLayout.reversePosition(position), wct);
                 } else {
                     position = getMainStagePosition();
                 }
@@ -494,8 +514,7 @@
 
     @SplitLayout.SplitPosition
     int getMainStagePosition() {
-        return mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT
-                ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT;
+        return SplitLayout.reversePosition(mSideStagePosition);
     }
 
     void setSideStagePosition(@SplitPosition int sideStagePosition,
@@ -542,6 +561,17 @@
         }
     }
 
+    void onFinishedWakingUp() {
+        if (mMainStage.isActive()) {
+            exitSplitScreenIfKeyguardOccluded();
+        }
+        mDeviceSleep = false;
+    }
+
+    void onFinishedGoingToSleep() {
+        mDeviceSleep = true;
+    }
+
     void exitSplitScreenOnHide(boolean exitSplitScreenOnHide) {
         mExitSplitScreenOnHide = exitSplitScreenOnHide;
     }
@@ -570,6 +600,19 @@
         applyExitSplitScreen(childrenToTop, wct, exitReason);
     }
 
+    private void exitSplitScreenIfKeyguardOccluded() {
+        final boolean mainStageVisible = mMainStageListener.mVisible;
+        final boolean oneStageVisible = mainStageVisible ^ mSideStageListener.mVisible;
+        if (mDeviceSleep && mKeyguardOccluded && oneStageVisible) {
+            // Only the stages include show-when-locked activity is visible while keyguard occluded.
+            // Dismiss split because there's show-when-locked activity showing on top of keyguard.
+            // Also make sure the task contains show-when-locked activity remains on top after split
+            // dismissed.
+            final StageTaskListener toTop = mainStageVisible ? mMainStage : mSideStage;
+            exitSplitScreen(toTop, EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
+        }
+    }
+
     private void applyExitSplitScreen(StageTaskListener childrenToTop,
             WindowContainerTransaction wct, @ExitReason int exitReason) {
         mRecentTasks.ifPresent(recentTasks -> {
@@ -735,17 +778,10 @@
 
     private void onStageRootTaskAppeared(StageListenerImpl stageListener) {
         if (mMainStageListener.mHasRootTask && mSideStageListener.mHasRootTask) {
-            mUseLegacySplit = mContext.getResources().getBoolean(R.bool.config_useLegacySplit);
             final WindowContainerTransaction wct = new WindowContainerTransaction();
             // Make the stages adjacent to each other so they occlude what's behind them.
             wct.setAdjacentRoots(mMainStage.mRootTaskInfo.token, mSideStage.mRootTaskInfo.token);
-
-            // Only sets side stage as launch-adjacent-flag-root when the device is not using legacy
-            // split to prevent new split behavior confusing users.
-            if (!mUseLegacySplit) {
-                wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
-            }
-
+            wct.setLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
             mTaskOrganizer.applyTransaction(wct);
         }
     }
@@ -753,13 +789,9 @@
     private void onStageRootTaskVanished(StageListenerImpl stageListener) {
         if (stageListener == mMainStageListener || stageListener == mSideStageListener) {
             final WindowContainerTransaction wct = new WindowContainerTransaction();
+            wct.clearLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
             // Deactivate the main stage if it no longer has a root task.
             mMainStage.deactivate(wct);
-
-            if (!mUseLegacySplit) {
-                wct.clearLaunchAdjacentFlagRoot(mSideStage.mRootTaskInfo.token);
-            }
-
             mTaskOrganizer.applyTransaction(wct);
         }
     }
@@ -798,14 +830,8 @@
             // like the cases keyguard showing or screen off.
                 exitSplitScreen(null /* childrenToTop */, EXIT_REASON_RETURN_HOME);
             }
-        } else if (mKeyguardOccluded) {
-            // At least one of the stages is visible while keyguard occluded. Dismiss split because
-            // there's show-when-locked activity showing on top of keyguard. Also make sure the
-            // task contains show-when-locked activity remains on top after split dismissed.
-            final StageTaskListener toTop =
-                    mainStageVisible ? mMainStage : (sideStageVisible ? mSideStage : null);
-            exitSplitScreen(toTop, EXIT_REASON_SCREEN_LOCKED_SHOW_ON_TOP);
         }
+        exitSplitScreenIfKeyguardOccluded();
 
         mSyncQueue.runInSync(t -> {
             // Same above, we only set root tasks and divider leash visibility when both stage
@@ -888,8 +914,7 @@
 
     @Override
     public void onDoubleTappedDivider() {
-        setSideStagePosition(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT
-                ? SPLIT_POSITION_BOTTOM_OR_RIGHT : SPLIT_POSITION_TOP_OR_LEFT, null /* wct */);
+        setSideStagePosition(SplitLayout.reversePosition(mSideStagePosition), null /* wct */);
         mLogger.logSwap(getMainStagePosition(), mMainStage.getTopChildTaskUid(),
                 getSideStagePosition(), mSideStage.getTopChildTaskUid(),
                 mSplitLayout.isLandscape());
@@ -1314,11 +1339,16 @@
         pw.println(prefix + TAG + " mDisplayId=" + mDisplayId);
         pw.println(innerPrefix + "mDividerVisible=" + mDividerVisible);
         pw.println(innerPrefix + "MainStage");
+        pw.println(childPrefix + "stagePosition=" + getMainStagePosition());
         pw.println(childPrefix + "isActive=" + mMainStage.isActive());
         mMainStageListener.dump(pw, childPrefix);
         pw.println(innerPrefix + "SideStage");
+        pw.println(childPrefix + "stagePosition=" + getSideStagePosition());
         mSideStageListener.dump(pw, childPrefix);
-        pw.println(innerPrefix + "mSplitLayout=" + mSplitLayout);
+        if (mMainStage.isActive()) {
+            pw.println(innerPrefix + "SplitLayout");
+            mSplitLayout.dump(pw, childPrefix);
+        }
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 190006e..5b08245 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -37,6 +37,7 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.internal.R;
 import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.SurfaceUtils;
@@ -102,7 +103,12 @@
         mSurfaceSession = surfaceSession;
         mIconProvider = iconProvider;
         mStageTaskUnfoldController = stageTaskUnfoldController;
-        taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
+
+        // No need to create root task if the device is using legacy split screen.
+        // TODO(b/199236198): Remove this check after totally deprecated legacy split.
+        if (!context.getResources().getBoolean(R.bool.config_useLegacySplit)) {
+            taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
+        }
     }
 
     int getChildCount() {
@@ -287,6 +293,10 @@
         }
     }
 
+    void addTask(ActivityManager.RunningTaskInfo task, WindowContainerTransaction wct) {
+        wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/);
+    }
+
     void setBounds(Rect bounds, WindowContainerTransaction wct) {
         wct.setBounds(mRootTaskInfo.token, bounds);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java
index 003d8a3..014f02b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashScreenExitAnimation.java
@@ -56,7 +56,7 @@
 public class SplashScreenExitAnimation implements Animator.AnimatorListener {
     private static final boolean DEBUG_EXIT_ANIMATION = false;
     private static final boolean DEBUG_EXIT_ANIMATION_BLEND = false;
-    private static final String TAG = StartingSurfaceDrawer.TAG;
+    private static final String TAG = StartingWindowController.TAG;
 
     private static final Interpolator ICON_INTERPOLATOR = new PathInterpolator(0.15f, 0f, 1f, 1f);
     private static final Interpolator MASK_RADIUS_INTERPOLATOR =
@@ -72,6 +72,7 @@
     private final int mAppRevealDuration;
     private final int mAnimationDuration;
     private final float mIconStartAlpha;
+    private final float mBrandingStartAlpha;
     private final TransactionPool mTransactionPool;
 
     private ValueAnimator mMainAnimator;
@@ -94,9 +95,17 @@
                 || iconView.getLayoutParams().height == 0) {
             mIconFadeOutDuration = 0;
             mIconStartAlpha = 0;
+            mBrandingStartAlpha = 0;
             mAppRevealDelay = 0;
         } else {
             iconView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+            // The branding view could only exists when the icon is present.
+            final View brandingView = view.getBrandingView();
+            if (brandingView != null) {
+                mBrandingStartAlpha = brandingView.getAlpha();
+            } else {
+                mBrandingStartAlpha = 0;
+            }
             mIconFadeOutDuration = context.getResources().getInteger(
                     R.integer.starting_window_app_reveal_icon_fade_out_duration);
             mAppRevealDelay = context.getResources().getInteger(
@@ -334,13 +343,21 @@
         // ignore
     }
 
-    private void onAnimationProgress(float linearProgress) {
-        View iconView = mSplashScreenView.getIconView();
+    private void onFadeOutProgress(float linearProgress) {
+        final float iconProgress = ICON_INTERPOLATOR.getInterpolation(
+                getProgress(linearProgress, 0 /* delay */, mIconFadeOutDuration));
+        final View iconView = mSplashScreenView.getIconView();
+        final View brandingView = mSplashScreenView.getBrandingView();
         if (iconView != null) {
-            final float iconProgress = ICON_INTERPOLATOR.getInterpolation(
-                    getProgress(linearProgress, 0 /* delay */, mIconFadeOutDuration));
             iconView.setAlpha(mIconStartAlpha * (1 - iconProgress));
         }
+        if (brandingView != null) {
+            brandingView.setAlpha(mBrandingStartAlpha * (1 - iconProgress));
+        }
+    }
+
+    private void onAnimationProgress(float linearProgress) {
+        onFadeOutProgress(linearProgress);
 
         final float revealLinearProgress = getProgress(linearProgress, mAppRevealDelay,
                 mAppRevealDuration);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index b191cab..a163f37 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -61,9 +61,11 @@
 import com.android.internal.graphics.palette.Palette;
 import com.android.internal.graphics.palette.Quantizer;
 import com.android.internal.graphics.palette.VariationalKMeansQuantizer;
+import com.android.internal.protolog.common.ProtoLog;
 import com.android.launcher3.icons.BaseIconFactory;
 import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.common.TransactionPool;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 import java.util.List;
 import java.util.function.Consumer;
@@ -78,8 +80,7 @@
  * @hide
  */
 public class SplashscreenContentDrawer {
-    private static final String TAG = StartingSurfaceDrawer.TAG;
-    private static final boolean DEBUG = StartingSurfaceDrawer.DEBUG_SPLASH_SCREEN;
+    private static final String TAG = StartingWindowController.TAG;
 
     // The acceptable area ratio of foreground_icon_area/background_icon_area, if there is an
     // icon which it's non-transparent foreground area is similar to it's background area, then
@@ -295,12 +296,10 @@
                 R.styleable.Window_windowSplashScreenIconBackgroundColor, def),
                 Color.TRANSPARENT);
         typedArray.recycle();
-        if (DEBUG) {
-            Slog.d(TAG, "window attributes color: "
-                    + Integer.toHexString(attrs.mWindowBgColor)
-                    + " icon " + attrs.mSplashScreenIcon + " duration " + attrs.mAnimationDuration
-                    + " brandImage " + attrs.mBrandingImage);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "getWindowAttrs: window attributes color: %s, replace icon: %b, avd duration: %d",
+                Integer.toHexString(attrs.mWindowBgColor), attrs.mSplashScreenIcon != null,
+                attrs.mAnimationDuration);
     }
 
     /** Creates the wrapper with system theme to avoid unexpected styles from app. */
@@ -385,9 +384,8 @@
                     iconDrawable = mContext.getPackageManager().getDefaultActivityIcon();
                 }
                 if (!processAdaptiveIcon(iconDrawable)) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "The icon is not an AdaptiveIconDrawable");
-                    }
+                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                            "The icon is not an AdaptiveIconDrawable");
                     Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "legacy_icon_factory");
                     final ShapeIconFactory factory = new ShapeIconFactory(
                             SplashscreenContentDrawer.this.mContext,
@@ -435,14 +433,14 @@
                     () -> new DrawableColorTester(iconForeground,
                             DrawableColorTester.TRANSLUCENT_FILTER /* filterType */),
                     () -> new DrawableColorTester(adaptiveIconDrawable.getBackground()));
-
-            if (DEBUG) {
-                Slog.d(TAG, "FgMainColor=" + Integer.toHexString(iconColor.mFgColor)
-                        + " BgMainColor=" + Integer.toHexString(iconColor.mBgColor)
-                        + " IsBgComplex=" + iconColor.mIsBgComplex
-                        + " FromCache=" + (iconColor.mReuseCount > 0)
-                        + " ThemeColor=" + Integer.toHexString(mThemeColor));
-            }
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                    "processAdaptiveIcon: FgMainColor=%s, BgMainColor=%s, "
+                            + "IsBgComplex=%b, FromCache=%b, ThemeColor=%s",
+                    Integer.toHexString(iconColor.mFgColor),
+                    Integer.toHexString(iconColor.mBgColor),
+                    iconColor.mIsBgComplex,
+                    iconColor.mReuseCount > 0,
+                    Integer.toHexString(mThemeColor));
 
             // Only draw the foreground of AdaptiveIcon to the splash screen if below condition
             // meet:
@@ -456,9 +454,8 @@
                     && (isRgbSimilarInHsv(mThemeColor, iconColor.mBgColor)
                             || (iconColor.mIsBgGrayscale
                                     && !isRgbSimilarInHsv(mThemeColor, iconColor.mFgColor)))) {
-                if (DEBUG) {
-                    Slog.d(TAG, "makeSplashScreenContentView: choose fg icon");
-                }
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                        "processAdaptiveIcon: choose fg icon");
                 // Reference AdaptiveIcon description, outer is 108 and inner is 72, so we
                 // scale by 192/160 if we only draw adaptiveIcon's foreground.
                 final float noBgScale =
@@ -469,9 +466,8 @@
                 mFinalIconSize = (int) (0.5f + mIconSize * noBgScale);
                 createIconDrawable(iconForeground, false);
             } else {
-                if (DEBUG) {
-                    Slog.d(TAG, "makeSplashScreenContentView: draw whole icon");
-                }
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                        "processAdaptiveIcon: draw whole icon");
                 createIconDrawable(iconDrawable, false);
             }
             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
@@ -504,9 +500,6 @@
                         mBrandingImageHeight);
             }
             final SplashScreenView splashScreenView = builder.build();
-            if (DEBUG) {
-                Slog.d(TAG, "fillViewWithIcon surfaceWindowView " + splashScreenView);
-            }
             if (mSuggestType != STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
                 splashScreenView.addOnAttachStateChangeListener(
                         new View.OnAttachStateChangeListener() {
@@ -536,10 +529,9 @@
         final float lumB = Color.luminance(b);
         final float contrastRatio = lumA > lumB
                 ? (lumA + 0.05f) / (lumB + 0.05f) : (lumB + 0.05f) / (lumA + 0.05f);
-        if (DEBUG) {
-            Slog.d(TAG, "isRgbSimilarInHsv a: " + Integer.toHexString(a)
-                    + " b " + Integer.toHexString(b) + " contrast ratio: " + contrastRatio);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "isRgbSimilarInHsv a:%s, b:%s, contrast ratio:%f",
+                Integer.toHexString(a), Integer.toHexString(b), contrastRatio);
         if (contrastRatio < 2) {
             return true;
         }
@@ -560,14 +552,11 @@
         final double square = squareH + squareS + squareV;
         final double mean = square / 3;
         final double root = Math.sqrt(mean);
-        if (DEBUG) {
-            Slog.d(TAG, "hsvDiff " + minAngle
-                    + " ah " + aHsv[0] + " bh " + bHsv[0]
-                    + " as " + aHsv[1] + " bs " + bHsv[1]
-                    + " av " + aHsv[2] + " bv " + bHsv[2]
-                    + " sqH " + squareH + " sqS " + squareS + " sqV " + squareV
-                    + " root " + root);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "isRgbSimilarInHsv hsvDiff: %d, ah: %f, bh: %f, as: %f, bs: %f, av: %f, bv: %f, "
+                        + "sqH: %f, sqS: %f, sqV: %f, rsm: %f",
+                minAngle, aHsv[0], bHsv[0], aHsv[1], bHsv[1], aHsv[2], bHsv[2],
+                squareH, squareS, squareV, root);
         return root < 0.1;
     }
 
@@ -598,9 +587,8 @@
             if (drawable instanceof LayerDrawable) {
                 LayerDrawable layerDrawable = (LayerDrawable) drawable;
                 if (layerDrawable.getNumberOfLayers() > 0) {
-                    if (DEBUG) {
-                        Slog.d(TAG, "replace drawable with bottom layer drawable");
-                    }
+                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                            "DrawableColorTester: replace drawable with bottom layer drawable");
                     drawable = layerDrawable.getDrawable(0);
                 }
             }
@@ -805,9 +793,8 @@
                         }
                     }
                     if (realSize == 0) {
-                        if (DEBUG) {
-                            Slog.d(TAG, "quantize: this is pure transparent image");
-                        }
+                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                                "DrawableTester quantize: pure transparent image");
                         mInnerQuantizer.quantize(pixels, maxColors);
                         return;
                     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
index 709e221..54281e0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
@@ -52,7 +52,7 @@
  */
 public class SplashscreenIconDrawableFactory {
 
-    private static final String TAG = "SplashscreenIconDrawableFactory";
+    private static final String TAG = StartingWindowController.TAG;
 
     /**
      * @return An array containing the foreground drawable at index 0 and if needed a background
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index bd48696..73f65b0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -61,10 +61,12 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.protolog.common.ProtoLog;
 import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 import java.util.function.Supplier;
 
@@ -106,9 +108,7 @@
  */
 @ShellSplashscreenThread
 public class StartingSurfaceDrawer {
-    static final String TAG = StartingSurfaceDrawer.class.getSimpleName();
-    static final boolean DEBUG_SPLASH_SCREEN = StartingWindowController.DEBUG_SPLASH_SCREEN;
-    static final boolean DEBUG_TASK_SNAPSHOT = StartingWindowController.DEBUG_TASK_SNAPSHOT;
+    private static final String TAG = StartingWindowController.TAG;
 
     private final Context mContext;
     private final DisplayManager mDisplayManager;
@@ -134,7 +134,8 @@
         mDisplayManager.getDisplay(DEFAULT_DISPLAY);
     }
 
-    private final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>();
+    @VisibleForTesting
+    final SparseArray<StartingWindowRecord> mStartingWindowRecords = new SparseArray<>();
 
     /**
      * Records of {@link SurfaceControlViewHost} where the splash screen icon animation is
@@ -178,11 +179,9 @@
 
         // replace with the default theme if the application didn't set
         final int theme = getSplashScreenTheme(windowInfo.splashScreenThemeResId, activityInfo);
-        if (DEBUG_SPLASH_SCREEN) {
-            Slog.d(TAG, "addSplashScreen " + activityInfo.packageName
-                    + " theme=" + Integer.toHexString(theme) + " task=" + taskInfo.taskId
-                    + " suggestType=" + suggestType);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "addSplashScreen for package: %s with theme: %s for task: %d, suggestType: %d",
+                activityInfo.packageName, Integer.toHexString(theme), taskId, suggestType);
         final Display display = getDisplay(displayId);
         if (display == null) {
             // Can't show splash screen on requested display, so skip showing at all.
@@ -207,10 +206,9 @@
 
         final Configuration taskConfig = taskInfo.getConfiguration();
         if (taskConfig.diffPublicOnly(context.getResources().getConfiguration()) != 0) {
-            if (DEBUG_SPLASH_SCREEN) {
-                Slog.d(TAG, "addSplashScreen: creating context based"
-                        + " on task Configuration " + taskConfig + " for splash screen");
-            }
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                    "addSplashScreen: creating context based on task Configuration %s",
+                    taskConfig);
             final Context overrideContext = context.createConfigurationContext(taskConfig);
             overrideContext.setTheme(theme);
             final TypedArray typedArray = overrideContext.obtainStyledAttributes(
@@ -221,10 +219,9 @@
                     // We want to use the windowBackground for the override context if it is
                     // available, otherwise we use the default one to make sure a themed starting
                     // window is displayed for the app.
-                    if (DEBUG_SPLASH_SCREEN) {
-                        Slog.d(TAG, "addSplashScreen: apply overrideConfig"
-                                + taskConfig + " to starting window resId=" + resId);
-                    }
+                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                            "addSplashScreen: apply overrideConfig %s",
+                            taskConfig);
                     context = overrideContext;
                 }
             } catch (Resources.NotFoundException e) {
@@ -460,12 +457,26 @@
      * Called when the content of a task is ready to show, starting window can be removed.
      */
     public void removeStartingWindow(StartingWindowRemovalInfo removalInfo) {
-        if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
-            Slog.d(TAG, "Task start finish, remove starting surface for task "
-                    + removalInfo.taskId);
-        }
-        removeWindowSynced(removalInfo);
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "Task start finish, remove starting surface for task: %d",
+                removalInfo.taskId);
+        removeWindowSynced(removalInfo, false /* immediately */);
+    }
 
+    /**
+     * Clear all starting windows immediately.
+     */
+    public void clearAllWindows() {
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "Clear all starting windows immediately");
+        final int taskSize = mStartingWindowRecords.size();
+        final int[] taskIds = new int[taskSize];
+        for (int i = taskSize - 1; i >= 0; --i) {
+            taskIds[i] = mStartingWindowRecords.keyAt(i);
+        }
+        for (int i = taskSize - 1; i >= 0; --i) {
+            removeWindowNoAnimate(taskIds[i]);
+        }
     }
 
     /**
@@ -485,10 +496,9 @@
         } else {
             parcelable = null;
         }
-        if (DEBUG_SPLASH_SCREEN) {
-            Slog.v(TAG, "Copying splash screen window view for task: " + taskId
-                    + " parcelable: " + parcelable);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "Copying splash screen window view for task: %d with parcelable %b",
+                taskId, parcelable != null);
         ActivityTaskManager.getInstance().onSplashScreenViewCopyFinished(taskId, parcelable);
     }
 
@@ -514,11 +524,9 @@
             return;
         }
         mAnimatedSplashScreenSurfaceHosts.remove(taskId);
-        if (DEBUG_SPLASH_SCREEN) {
-            String reason = fromServer ? "Server cleaned up" : "App removed";
-            Slog.v(TAG, reason + "the splash screen. Releasing SurfaceControlViewHost for task:"
-                    + taskId);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "%s the splash screen. Releasing SurfaceControlViewHost for task: %d",
+                fromServer ? "Server cleaned up" : "App removed", taskId);
         SplashScreenView.releaseIconHost(viewHost);
     }
 
@@ -550,7 +558,8 @@
         return shouldSaveView;
     }
 
-    private void saveSplashScreenRecord(IBinder appToken, int taskId, View view,
+    @VisibleForTesting
+    void saveSplashScreenRecord(IBinder appToken, int taskId, View view,
             @StartingWindowType int suggestType) {
         final StartingWindowRecord tView = new StartingWindowRecord(appToken, view,
                 null/* TaskSnapshotWindow */, suggestType);
@@ -559,28 +568,27 @@
 
     private void removeWindowNoAnimate(int taskId) {
         mTmpRemovalInfo.taskId = taskId;
-        removeWindowSynced(mTmpRemovalInfo);
+        removeWindowSynced(mTmpRemovalInfo, true /* immediately */);
     }
 
     void onImeDrawnOnTask(int taskId) {
         final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
         if (record != null && record.mTaskSnapshotWindow != null
                 && record.mTaskSnapshotWindow.hasImeSurface()) {
-            record.mTaskSnapshotWindow.removeImmediately();
+            removeWindowNoAnimate(taskId);
         }
-        mStartingWindowRecords.remove(taskId);
     }
 
-    protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo) {
+    protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo, boolean immediately) {
         final int taskId = removalInfo.taskId;
         final StartingWindowRecord record = mStartingWindowRecords.get(taskId);
         if (record != null) {
             if (record.mDecorView != null) {
-                if (DEBUG_SPLASH_SCREEN) {
-                    Slog.v(TAG, "Removing splash screen window for task: " + taskId);
-                }
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                        "Removing splash screen window for task: %d", taskId);
                 if (record.mContentView != null) {
-                    if (record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
+                    if (immediately
+                            || record.mSuggestType == STARTING_WINDOW_TYPE_LEGACY_SPLASH_SCREEN) {
                         removeWindowInner(record.mDecorView, false);
                     } else {
                         if (removalInfo.playRevealAnimation) {
@@ -601,11 +609,14 @@
                 mStartingWindowRecords.remove(taskId);
             }
             if (record.mTaskSnapshotWindow != null) {
-                if (DEBUG_TASK_SNAPSHOT) {
-                    Slog.v(TAG, "Removing task snapshot window for " + taskId);
+                ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                        "Removing task snapshot window for %d", taskId);
+                if (immediately) {
+                    record.mTaskSnapshotWindow.removeImmediately();
+                } else {
+                    record.mTaskSnapshotWindow.scheduleRemove(() ->
+                            mStartingWindowRecords.remove(taskId), removalInfo.deferRemoveForIme);
                 }
-                record.mTaskSnapshotWindow.scheduleRemove(
-                        () -> mStartingWindowRecords.remove(taskId), removalInfo.deferRemoveForIme);
             }
         }
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
index e98a3e8..487eb70 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -29,9 +29,7 @@
 import android.content.Context;
 import android.graphics.Color;
 import android.os.IBinder;
-import android.os.RemoteException;
 import android.os.Trace;
-import android.util.Slog;
 import android.util.SparseIntArray;
 import android.window.StartingWindowInfo;
 import android.window.StartingWindowInfo.StartingWindowType;
@@ -66,10 +64,7 @@
  * @hide
  */
 public class StartingWindowController implements RemoteCallable<StartingWindowController> {
-    private static final String TAG = StartingWindowController.class.getSimpleName();
-
-    public static final boolean DEBUG_SPLASH_SCREEN = false;
-    public static final boolean DEBUG_TASK_SNAPSHOT = false;
+    public static final String TAG = "ShellStartingWindow";
 
     private static final long TASK_BG_COLOR_RETAIN_TIME_MS = 5000;
 
@@ -199,6 +194,18 @@
     }
 
     /**
+     * Clear all starting window immediately, called this method when releasing the task organizer.
+     */
+    public void clearAllWindows() {
+        mSplashScreenExecutor.execute(() -> {
+            mStartingSurfaceDrawer.clearAllWindows();
+            synchronized (mTaskBackgroundColors) {
+                mTaskBackgroundColors.clear();
+            }
+        });
+    }
+
+    /**
      * The interface for calls from outside the Shell, within the host process.
      */
     private class StartingSurfaceImpl implements StartingSurface {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index 3e88c46..6643ca1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -85,8 +85,10 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.DecorView;
+import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.view.BaseIWindow;
 import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
 
 /**
  * This class represents a starting window that shows a snapshot.
@@ -113,8 +115,7 @@
             | FLAG_SCALED
             | FLAG_SECURE;
 
-    private static final String TAG = StartingSurfaceDrawer.TAG;
-    private static final boolean DEBUG = StartingSurfaceDrawer.DEBUG_TASK_SNAPSHOT;
+    private static final String TAG = StartingWindowController.TAG;
     private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
 
     private static final long DELAY_REMOVAL_TIME_GENERAL = 100;
@@ -158,9 +159,8 @@
             @NonNull Runnable clearWindowHandler) {
         final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
         final int taskId = runningTaskInfo.taskId;
-        if (DEBUG) {
-            Slog.d(TAG, "create taskSnapshot surface for task: " + taskId);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "create taskSnapshot surface for task: %d", taskId);
 
         final WindowManager.LayoutParams attrs = info.topOpaqueWindowLayoutParams;
         final WindowManager.LayoutParams mainWindowParams = info.mainWindowLayoutParams;
@@ -327,17 +327,15 @@
                 ? MAX_DELAY_REMOVAL_TIME_IME_VISIBLE
                 : DELAY_REMOVAL_TIME_GENERAL;
         mSplashScreenExecutor.executeDelayed(mScheduledRunnable, delayRemovalTime);
-        if (DEBUG) {
-            Slog.d(TAG, "Defer removing snapshot surface in " + delayRemovalTime);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "Defer removing snapshot surface in %d", delayRemovalTime);
     }
 
     void removeImmediately() {
         mSplashScreenExecutor.removeCallbacks(mScheduledRunnable);
         try {
-            if (DEBUG) {
-                Slog.d(TAG, "Removing taskSnapshot surface, mHasDrawn: " + mHasDrawn);
-            }
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                    "Removing taskSnapshot surface, mHasDrawn=%b", mHasDrawn);
             mSession.remove(mWindow);
         } catch (RemoteException e) {
             // nothing
@@ -363,9 +361,8 @@
     }
 
     private void drawSnapshot() {
-        if (DEBUG) {
-            Slog.d(TAG, "Drawing snapshot surface sizeMismatch= " + mSizeMismatch);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "Drawing snapshot surface sizeMismatch=%b", mSizeMismatch);
         if (mSizeMismatch) {
             // The dimensions of the buffer and the window don't match, so attaching the buffer
             // will fail. Better create a child window with the exact dimensions and fill the parent
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
index cbf8e79..51a48a2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/phone/PhoneStartingWindowTypeAlgorithm.java
@@ -31,13 +31,11 @@
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_TASK_SWITCH;
 import static android.window.StartingWindowInfo.TYPE_PARAMETER_USE_EMPTY_SPLASH_SCREEN;
 
-import static com.android.wm.shell.startingsurface.StartingWindowController.DEBUG_SPLASH_SCREEN;
-import static com.android.wm.shell.startingsurface.StartingWindowController.DEBUG_TASK_SNAPSHOT;
-
-import android.util.Slog;
 import android.window.StartingWindowInfo;
 import android.window.TaskSnapshot;
 
+import com.android.internal.protolog.common.ProtoLog;
+import com.android.wm.shell.protolog.ShellProtoLogGroup;
 import com.android.wm.shell.startingsurface.StartingWindowTypeAlgorithm;
 
 /**
@@ -45,8 +43,6 @@
  * At the moment also used on Android Auto and Wear OS.
  */
 public class PhoneStartingWindowTypeAlgorithm implements StartingWindowTypeAlgorithm {
-    private static final String TAG = PhoneStartingWindowTypeAlgorithm.class.getSimpleName();
-
     @Override
     public int getSuggestedWindowType(StartingWindowInfo windowInfo) {
         final int parameter = windowInfo.startingWindowTypeParameter;
@@ -62,17 +58,19 @@
         final boolean activityDrawn = (parameter & TYPE_PARAMETER_ACTIVITY_DRAWN) != 0;
         final boolean topIsHome = windowInfo.taskInfo.topActivityType == ACTIVITY_TYPE_HOME;
 
-        if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
-            Slog.d(TAG, "preferredStartingWindowType newTask:" + newTask
-                    + " taskSwitch:" + taskSwitch
-                    + " processRunning:" + processRunning
-                    + " allowTaskSnapshot:" + allowTaskSnapshot
-                    + " activityCreated:" + activityCreated
-                    + " useEmptySplashScreen:" + useEmptySplashScreen
-                    + " legacySplashScreen:" + legacySplashScreen
-                    + " activityDrawn:" + activityDrawn
-                    + " topIsHome:" + topIsHome);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "preferredStartingWindowType "
+                        + "newTask=%b, "
+                        + "taskSwitch=%b, "
+                        + "processRunning=%b, "
+                        + "allowTaskSnapshot=%b, "
+                        + "activityCreated=%b, "
+                        + "useEmptySplashScreen=%b, "
+                        + "legacySplashScreen=%b, "
+                        + "activityDrawn=%b, "
+                        + "topIsHome=%b",
+                newTask, taskSwitch, processRunning, allowTaskSnapshot, activityCreated,
+                useEmptySplashScreen, legacySplashScreen, activityDrawn, topIsHome);
 
         if (!topIsHome) {
             if (!processRunning || newTask || (taskSwitch && !activityCreated)) {
@@ -111,26 +109,24 @@
     private boolean isSnapshotCompatible(StartingWindowInfo windowInfo) {
         final TaskSnapshot snapshot = windowInfo.taskSnapshot;
         if (snapshot == null) {
-            if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
-                Slog.d(TAG, "isSnapshotCompatible no snapshot " + windowInfo.taskInfo.taskId);
-            }
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                    "isSnapshotCompatible no snapshot, taskId=%d",
+                    windowInfo.taskInfo.taskId);
             return false;
         }
         if (!snapshot.getTopActivityComponent().equals(windowInfo.taskInfo.topActivity)) {
-            if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
-                Slog.d(TAG, "isSnapshotCompatible obsoleted snapshot "
-                        + windowInfo.taskInfo.topActivity);
-            }
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                    "isSnapshotCompatible obsoleted snapshot for %s",
+                    windowInfo.taskInfo.topActivity);
             return false;
         }
 
         final int taskRotation = windowInfo.taskInfo.configuration
                 .windowConfiguration.getRotation();
         final int snapshotRotation = snapshot.getRotation();
-        if (DEBUG_SPLASH_SCREEN || DEBUG_TASK_SNAPSHOT) {
-            Slog.d(TAG, "isSnapshotCompatible rotation " + taskRotation
-                    + " snapshot " + snapshotRotation);
-        }
+        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                "isSnapshotCompatible taskRotation=%d, snapshotRotation=%d",
+                taskRotation, snapshotRotation);
         return taskRotation == snapshotRotation;
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 7abda99..a0d9d03 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -52,9 +52,12 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
+import android.annotation.ColorInt;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.app.ActivityThread;
 import android.content.Context;
+import android.graphics.Color;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.hardware.HardwareBuffer;
@@ -66,6 +69,7 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.WindowManager;
+import android.view.WindowManager.TransitionType;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
 import android.view.animation.Transformation;
@@ -78,6 +82,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.AttributeCache;
+import com.android.internal.policy.ScreenDecorationsUtils;
 import com.android.internal.policy.TransitionAnimation;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.wm.shell.common.DisplayController;
@@ -292,9 +297,12 @@
             finishCallback.onTransitionFinished(null /* wct */, null /* wctCB */);
         };
 
+        boolean requireBackgroundForTransition = false;
+
         final int wallpaperTransit = getWallpaperTransitType(info);
         for (int i = info.getChanges().size() - 1; i >= 0; --i) {
             final TransitionInfo.Change change = info.getChanges().get(i);
+            final boolean isTask = change.getTaskInfo() != null;
 
             if (change.getMode() == TRANSIT_CHANGE && (change.getFlags() & FLAG_IS_DISPLAY) != 0) {
                 int rotateDelta = change.getEndRotation() - change.getStartRotation();
@@ -342,7 +350,7 @@
                 startTransaction.setPosition(change.getLeash(),
                         change.getEndAbsBounds().left - change.getEndRelOffset().x,
                         change.getEndAbsBounds().top - change.getEndRelOffset().y);
-                if (change.getTaskInfo() != null) {
+                if (isTask) {
                     // Skip non-tasks since those usually have null bounds.
                     startTransaction.setWindowCrop(change.getLeash(),
                             change.getEndAbsBounds().width(), change.getEndAbsBounds().height());
@@ -354,14 +362,34 @@
 
             Animation a = loadAnimation(info, change, wallpaperTransit);
             if (a != null) {
+                if (changeRequiresBackground(info, change)) {
+                    requireBackgroundForTransition = true;
+                }
+
+                float cornerRadius = 0;
+                if (a.hasRoundedCorners() && isTask) {
+                    // hasRoundedCorners is currently only enabled for tasks
+                    final Context displayContext =
+                            mDisplayController.getDisplayContext(change.getTaskInfo().displayId);
+                    cornerRadius =
+                            ScreenDecorationsUtils.getWindowCornerRadius(displayContext);
+                }
+
                 startSurfaceAnimation(animations, a, change.getLeash(), onAnimFinish,
-                        mTransactionPool, mMainExecutor, mAnimExecutor, null /* position */);
+                        mTransactionPool, mMainExecutor, mAnimExecutor, null /* position */,
+                        cornerRadius, change.getEndAbsBounds());
 
                 if (info.getAnimationOptions() != null) {
-                    attachThumbnail(animations, onAnimFinish, change, info.getAnimationOptions());
+                    attachThumbnail(animations, onAnimFinish, change, info.getAnimationOptions(),
+                            cornerRadius);
                 }
             }
         }
+
+        if (requireBackgroundForTransition) {
+            addBackgroundToTransition(info.getRootLeash(), startTransaction, finishTransaction);
+        }
+
         startTransaction.apply();
         TransitionMetrics.getInstance().reportAnimationStart(transition);
         // run finish now in-case there are no animations
@@ -369,6 +397,40 @@
         return true;
     }
 
+    private boolean changeRequiresBackground(TransitionInfo info,
+            TransitionInfo.Change change) {
+        final boolean isTask = change.getTaskInfo() != null;
+        final @TransitionType int type = info.getType();
+        final boolean isOpenOrCloseTransition = type == TRANSIT_OPEN || type == TRANSIT_CLOSE
+                || type == TRANSIT_TO_FRONT || type == TRANSIT_TO_BACK;
+        return isTask && isOpenOrCloseTransition;
+    }
+
+    private void addBackgroundToTransition(
+            @NonNull SurfaceControl rootLeash,
+            @NonNull SurfaceControl.Transaction startTransaction,
+            @NonNull SurfaceControl.Transaction finishTransaction
+    ) {
+        final Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext();
+        final @ColorInt int overviewBackgroundColor =
+                uiContext.getColor(R.color.overview_background);
+        final Color bgColor = Color.valueOf(overviewBackgroundColor);
+        final float[] colorArray = new float[] { bgColor.red(), bgColor.green(), bgColor.blue() };
+
+        final SurfaceControl animationBackgroundSurface = new SurfaceControl.Builder()
+                .setName("Animation Background")
+                .setParent(rootLeash)
+                .setColorLayer()
+                .setOpaque(true)
+                .build();
+
+        startTransaction
+                .setLayer(animationBackgroundSurface, Integer.MIN_VALUE)
+                .setColor(animationBackgroundSurface, colorArray)
+                .show(animationBackgroundSurface);
+        finishTransaction.remove(animationBackgroundSurface);
+    }
+
     @Nullable
     @Override
     public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@@ -508,7 +570,7 @@
             @NonNull Animation anim, @NonNull SurfaceControl leash,
             @NonNull Runnable finishCallback, @NonNull TransactionPool pool,
             @NonNull ShellExecutor mainExecutor, @NonNull ShellExecutor animExecutor,
-            @Nullable Point position) {
+            @Nullable Point position, float cornerRadius, @Nullable Rect clipRect) {
         final SurfaceControl.Transaction transaction = pool.acquire();
         final ValueAnimator va = ValueAnimator.ofFloat(0f, 1f);
         final Transformation transformation = new Transformation();
@@ -520,12 +582,12 @@
             final long currentPlayTime = Math.min(va.getDuration(), va.getCurrentPlayTime());
 
             applyTransformation(currentPlayTime, transaction, leash, anim, transformation, matrix,
-                    position);
+                    position, cornerRadius, clipRect);
         });
 
         final Runnable finisher = () -> {
             applyTransformation(va.getDuration(), transaction, leash, anim, transformation, matrix,
-                    position);
+                    position, cornerRadius, clipRect);
 
             pool.release(transaction);
             mainExecutor.execute(() -> {
@@ -550,23 +612,24 @@
 
     private void attachThumbnail(@NonNull ArrayList<Animator> animations,
             @NonNull Runnable finishCallback, TransitionInfo.Change change,
-            TransitionInfo.AnimationOptions options) {
+            TransitionInfo.AnimationOptions options, float cornerRadius) {
         final boolean isTask = change.getTaskInfo() != null;
         final boolean isOpen = Transitions.isOpeningType(change.getMode());
         final boolean isClose = Transitions.isClosingType(change.getMode());
         if (isOpen) {
             if (options.getType() == ANIM_OPEN_CROSS_PROFILE_APPS && isTask) {
-                attachCrossProfileThunmbnailAnimation(animations, finishCallback, change);
+                attachCrossProfileThunmbnailAnimation(animations, finishCallback, change,
+                        cornerRadius);
             } else if (options.getType() == ANIM_THUMBNAIL_SCALE_UP) {
-                attachThumbnailAnimation(animations, finishCallback, change, options);
+                attachThumbnailAnimation(animations, finishCallback, change, options, cornerRadius);
             }
         } else if (isClose && options.getType() == ANIM_THUMBNAIL_SCALE_DOWN) {
-            attachThumbnailAnimation(animations, finishCallback, change, options);
+            attachThumbnailAnimation(animations, finishCallback, change, options, cornerRadius);
         }
     }
 
     private void attachCrossProfileThunmbnailAnimation(@NonNull ArrayList<Animator> animations,
-            @NonNull Runnable finishCallback, TransitionInfo.Change change) {
+            @NonNull Runnable finishCallback, TransitionInfo.Change change, float cornerRadius) {
         final int thumbnailDrawableRes = change.getTaskInfo().userId == mCurrentUserId
                 ? R.drawable.ic_account_circle : R.drawable.ic_corp_badge;
         final Rect bounds = change.getEndAbsBounds();
@@ -594,12 +657,13 @@
         a.restrictDuration(MAX_ANIMATION_DURATION);
         a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
         startSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
-                mMainExecutor, mAnimExecutor, new Point(bounds.left, bounds.top));
+                mMainExecutor, mAnimExecutor, new Point(bounds.left, bounds.top),
+                cornerRadius, change.getEndAbsBounds());
     }
 
     private void attachThumbnailAnimation(@NonNull ArrayList<Animator> animations,
             @NonNull Runnable finishCallback, TransitionInfo.Change change,
-            TransitionInfo.AnimationOptions options) {
+            TransitionInfo.AnimationOptions options, float cornerRadius) {
         final SurfaceControl.Transaction transaction = mTransactionPool.acquire();
         final WindowThumbnail wt = WindowThumbnail.createAndAttach(mSurfaceSession,
                 change.getLeash(), options.getThumbnail(), transaction);
@@ -618,7 +682,8 @@
         a.restrictDuration(MAX_ANIMATION_DURATION);
         a.scaleCurrentDuration(mTransitionAnimationScaleSetting);
         startSurfaceAnimation(animations, a, wt.getSurface(), finisher, mTransactionPool,
-                mMainExecutor, mAnimExecutor, null /* position */);
+                mMainExecutor, mAnimExecutor, null /* position */,
+                cornerRadius, change.getEndAbsBounds());
     }
 
     private static int getWallpaperTransitType(TransitionInfo info) {
@@ -650,13 +715,19 @@
 
     private static void applyTransformation(long time, SurfaceControl.Transaction t,
             SurfaceControl leash, Animation anim, Transformation transformation, float[] matrix,
-            Point position) {
+            Point position, float cornerRadius, @Nullable Rect clipRect) {
         anim.getTransformation(time, transformation);
         if (position != null) {
             transformation.getMatrix().postTranslate(position.x, position.y);
         }
         t.setMatrix(leash, transformation.getMatrix(), matrix);
         t.setAlpha(leash, transformation.getAlpha());
+        if (anim.hasRoundedCorners() && cornerRadius > 0 && clipRect != null) {
+            // We can only apply rounded corner if a crop is set
+            t.setWindowCrop(leash, clipRect);
+            t.setCornerRadius(leash, cornerRadius);
+        }
+
         t.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId());
         t.apply();
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
index 13c670a..45d8be1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/ScreenRotationAnimation.java
@@ -292,14 +292,16 @@
             @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor,
             @NonNull ShellExecutor animExecutor) {
         startSurfaceAnimation(animations, mRotateEnterAnimation, mSurfaceControl, finishCallback,
-                mTransactionPool, mainExecutor, animExecutor, null /* position */);
+                mTransactionPool, mainExecutor, animExecutor, null /* position */,
+                0 /* cornerRadius */, null /* clipRect */);
     }
 
     private void startScreenshotRotationAnimation(@NonNull ArrayList<Animator> animations,
             @NonNull Runnable finishCallback, @NonNull ShellExecutor mainExecutor,
             @NonNull ShellExecutor animExecutor) {
         startSurfaceAnimation(animations, mRotateExitAnimation, mAnimLeash, finishCallback,
-                mTransactionPool, mainExecutor, animExecutor, null /* position */);
+                mTransactionPool, mainExecutor, animExecutor, null /* position */,
+                0 /* cornerRadius */, null /* clipRect */);
     }
 
     private void startColorAnimation(float animationScale, @NonNull ShellExecutor animExecutor) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java
index 74e4812..367676f 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/ShellUnfoldProgressProvider.java
@@ -26,10 +26,16 @@
  */
 public interface ShellUnfoldProgressProvider {
 
+    // This is a temporary workaround until we move the progress providers into the Shell or
+    // refactor the dependencies. TLDR, the base module depends on this provider to determine if the
+    // FullscreenUnfoldController is available, but this check can't rely on an optional component.
+    public static final ShellUnfoldProgressProvider NO_PROVIDER =
+            new ShellUnfoldProgressProvider() {};
+
     /**
      * Adds a transition listener
      */
-    void addListener(Executor executor, UnfoldListener listener);
+    default void addListener(Executor executor, UnfoldListener listener) {}
 
     /**
      * Listener for receiving unfold updates
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/StagedSplitBounds.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/StagedSplitBounds.java
index aadf792..a0c84cc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/StagedSplitBounds.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/StagedSplitBounds.java
@@ -19,6 +19,8 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Objects;
+
 /**
  * Container of various information needed to display split screen
  * tasks/leashes/etc in Launcher
@@ -93,6 +95,24 @@
     }
 
     @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof StagedSplitBounds)) {
+            return false;
+        }
+        // Only need to check the base fields (the other fields are derived from these)
+        final StagedSplitBounds other = (StagedSplitBounds) obj;
+        return Objects.equals(leftTopBounds, other.leftTopBounds)
+                && Objects.equals(rightBottomBounds, other.rightBottomBounds)
+                && leftTopTaskId == other.leftTopTaskId
+                && rightBottomTaskId == other.rightBottomTaskId;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(leftTopBounds, rightBottomBounds, leftTopTaskId, rightBottomTaskId);
+    }
+
+    @Override
     public String toString() {
         return "LeftTop: " + leftTopBounds + ", taskId: " + leftTopTaskId + "\n"
                 + "RightBottom: " + rightBottomBounds + ", taskId: " + rightBottomTaskId +  "\n"
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
index ad4ccc0..574a9f4 100644
--- a/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidTest.xml
@@ -16,10 +16,6 @@
         <!-- restart launcher to activate TAPL -->
         <option name="run-command" value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher" />
     </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.DeviceCleaner">
-        <!-- reboot the device to teardown any crashed tests -->
-        <option name="cleanup-action" value="REBOOT" />
-    </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true"/>
         <option name="test-file-name" value="WMShellFlickerTests.apk"/>
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
index ecc2d31..e6c2f38e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestCannotPairNonResizeableApps.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.flicker.apppairs
 
+import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
@@ -24,11 +25,13 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group1
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.wm.shell.flicker.appPairsDividerIsInvisibleAtEnd
 import com.android.wm.shell.flicker.helpers.AppPairsHelper
 import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.resetMultiWindowConfig
 import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.setSupportsNonResizableMultiWindow
 import org.junit.After
+import org.junit.Assume.assumeFalse
 import org.junit.Before
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -80,9 +83,13 @@
     @Test
     override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
 
-    @FlakyTest
+    @Postsubmit
     @Test
-    override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
index 04c82e5..1a3e42c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestPairPrimaryAndSecondaryApps.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.flicker.apppairs
 
+import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
@@ -24,10 +25,12 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group1
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.wm.shell.flicker.APP_PAIR_SPLIT_DIVIDER_COMPONENT
 import com.android.wm.shell.flicker.appPairsDividerIsVisibleAtEnd
 import com.android.wm.shell.flicker.helpers.AppPairsHelper
 import com.android.wm.shell.flicker.helpers.AppPairsHelper.Companion.waitAppsShown
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -65,9 +68,13 @@
     @Test
     override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
 
-    @FlakyTest
+    @Postsubmit
     @Test
-    override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt
index b7d3ba6..5c78b29 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestSupportPairNonResizeableApps.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.flicker.apppairs
 
+import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
@@ -24,11 +25,13 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group1
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.wm.shell.flicker.appPairsDividerIsVisibleAtEnd
 import com.android.wm.shell.flicker.helpers.AppPairsHelper
 import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.resetMultiWindowConfig
 import com.android.wm.shell.flicker.helpers.MultiWindowHelper.Companion.setSupportsNonResizableMultiWindow
 import org.junit.After
+import org.junit.Assume.assumeFalse
 import org.junit.Before
 import org.junit.FixMethodOrder
 import org.junit.Test
@@ -84,9 +87,13 @@
     @Test
     override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
 
-    @FlakyTest
+    @Postsubmit
     @Test
-    override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
index f6ce3d4..251d92d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/AppPairsTestUnpairPrimaryAndSecondaryApps.kt
@@ -17,6 +17,7 @@
 package com.android.wm.shell.flicker.apppairs
 
 import android.os.SystemClock
+import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
@@ -25,10 +26,12 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group1
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.wm.shell.flicker.APP_PAIR_SPLIT_DIVIDER_COMPONENT
 import com.android.wm.shell.flicker.appPairsDividerIsInvisibleAtEnd
 import com.android.wm.shell.flicker.helpers.AppPairsHelper
 import com.android.wm.shell.flicker.helpers.AppPairsHelper.Companion.waitAppsShown
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -69,9 +72,13 @@
     @Test
     override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
 
-    @FlakyTest
+    @Postsubmit
     @Test
-    override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
index 13824b8..d47057f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsInAppPairsMode.kt
@@ -16,9 +16,9 @@
 
 package com.android.wm.shell.flicker.apppairs
 
+import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
-import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.FlickerTestParameter
@@ -87,7 +87,7 @@
         testSpec.appPairsPrimaryBoundsIsVisibleAtEnd(testSpec.endRotation,
             primaryApp.component)
 
-    @FlakyTest
+    @Postsubmit
     @Test
     fun appPairsSecondaryBoundsIsVisibleAtEnd() =
         testSpec.appPairsSecondaryBoundsIsVisibleAtEnd(testSpec.endRotation,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
index c003084..097867a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/apppairs/RotateTwoLaunchedAppsRotateAndEnterAppPairsMode.kt
@@ -16,9 +16,9 @@
 
 package com.android.wm.shell.flicker.apppairs
 
+import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
-import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.FlickerTestParameter
@@ -89,13 +89,13 @@
         }
     }
 
-    @FlakyTest(bugId = 172776659)
+    @Postsubmit
     @Test
     fun appPairsPrimaryBoundsIsVisibleAtEnd() =
         testSpec.appPairsPrimaryBoundsIsVisibleAtEnd(testSpec.endRotation,
             primaryApp.component)
 
-    @FlakyTest(bugId = 172776659)
+    @Postsubmit
     @Test
     fun appPairsSecondaryBoundsIsVisibleAtEnd() =
         testSpec.appPairsSecondaryBoundsIsVisibleAtEnd(testSpec.endRotation,
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
index 1605d80..a928bbd 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
@@ -18,7 +18,7 @@
 
 import android.content.Context
 import android.graphics.Point
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
 import android.util.DisplayMetrics
 import android.view.WindowManager
 import androidx.test.filters.RequiresDevice
@@ -66,7 +66,7 @@
             }
         }
 
-    @Postsubmit
+    @Presubmit
     @Test
     fun testAppIsAlwaysVisible() {
         testSpec.assertLayers {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
index a8f17a75..64636be 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
@@ -16,7 +16,7 @@
 
 package com.android.wm.shell.flicker.bubble
 
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.FlickerTestParameter
@@ -49,7 +49,7 @@
             }
         }
 
-    @Postsubmit
+    @Presubmit
     @Test
     fun testAppIsAlwaysVisible() {
         testSpec.assertLayers {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
index 3885155..ef7d65e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
@@ -16,7 +16,6 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.platform.test.annotations.Postsubmit
 import android.view.Surface
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
@@ -74,7 +73,7 @@
             splitScreenApp.component, secondaryApp.component,
             FlickerComponentName.SNAPSHOT)
 
-    @Postsubmit
+    @FlakyTest
     @Test
     fun layerBecomesInvisible() {
         testSpec.assertLayers {
@@ -94,11 +93,11 @@
         }
     }
 
-    @Postsubmit
+    @FlakyTest
     @Test
     fun navBarWindowIsVisible() = testSpec.navBarWindowIsVisible()
 
-    @Postsubmit
+    @FlakyTest
     @Test
     fun statusBarWindowIsVisible() = testSpec.statusBarWindowIsVisible()
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt
index 079a6ef..c1fba7d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenFromRecentNotSupportNonResizable.kt
@@ -16,9 +16,9 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.FlickerTestParameter
@@ -124,7 +124,7 @@
         }
     }
 
-    @Postsubmit
+    @FlakyTest
     @Test
     fun nonResizableAppWindowBecomesVisible() {
         testSpec.assertWm {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
index 5fe13e0..77fb101 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
@@ -16,9 +16,9 @@
 
 package com.android.wm.shell.flicker.legacysplitscreen
 
-import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.FlickerTestParameter
@@ -27,6 +27,7 @@
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.entireScreenCovered
 import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
 import com.android.server.wm.flicker.helpers.setRotation
@@ -40,6 +41,7 @@
 import com.android.server.wm.traces.common.FlickerComponentName
 import com.android.wm.shell.flicker.dockedStackDividerBecomesInvisible
 import com.android.wm.shell.flicker.helpers.SimpleAppHelper
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -110,17 +112,21 @@
 
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
     fun statusBarLayerIsVisible() = testSpec.statusBarLayerIsVisible()
 
-    @Postsubmit
+    @FlakyTest
     @Test
     fun dockedStackDividerBecomesInvisible() = testSpec.dockedStackDividerBecomesInvisible()
 
-    @Postsubmit
+    @FlakyTest
     @Test
     fun layerBecomesInvisible() {
         testSpec.assertLayers {
@@ -130,7 +136,7 @@
         }
     }
 
-    @Postsubmit
+    @FlakyTest
     @Test
     fun focusDoesNotChange() {
         testSpec.assertEventLog {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
index a238bc2..6041e23 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
@@ -30,6 +30,7 @@
 import com.android.server.wm.flicker.entireScreenCovered
 import com.android.server.wm.flicker.helpers.ImeAppHelper
 import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.resizeSplitScreen
 import com.android.server.wm.flicker.helpers.setRotation
@@ -44,6 +45,7 @@
 import com.android.wm.shell.flicker.DOCKED_STACK_DIVIDER_COMPONENT
 import com.android.wm.shell.flicker.helpers.SimpleAppHelper
 import com.android.wm.shell.flicker.testapp.Components
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -134,7 +136,11 @@
     fun navBarLayerRotatesAndScales() = testSpec.navBarLayerRotatesAndScales()
 
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @Test
     fun topAppLayerIsAlwaysVisible() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
index 50cd548..e44d7d6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
@@ -25,6 +25,7 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group2
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
@@ -34,6 +35,7 @@
 import com.android.wm.shell.flicker.dockedStackDividerIsVisibleAtEnd
 import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisibleAtEnd
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -77,7 +79,11 @@
 
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
index 8d52225..d33d92b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
@@ -25,6 +25,7 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group2
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
@@ -34,6 +35,7 @@
 import com.android.wm.shell.flicker.dockedStackDividerIsVisibleAtEnd
 import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisibleAtEnd
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -76,7 +78,11 @@
 
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
index 070f636..ece68df 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
@@ -24,6 +24,7 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group2
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.reopenAppFromOverview
 import com.android.server.wm.flicker.helpers.setRotation
@@ -35,6 +36,7 @@
 import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisibleAtEnd
 import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisibleAtEnd
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -85,7 +87,11 @@
 
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
index fabbd26..127301f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
@@ -25,6 +25,7 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group2
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.launchSplitScreen
 import com.android.server.wm.flicker.helpers.reopenAppFromOverview
 import com.android.server.wm.flicker.helpers.setRotation
@@ -36,6 +37,7 @@
 import com.android.wm.shell.flicker.dockedStackPrimaryBoundsIsVisibleAtEnd
 import com.android.wm.shell.flicker.dockedStackSecondaryBoundsIsVisibleAtEnd
 import com.android.wm.shell.flicker.helpers.SplitScreenHelper
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -91,7 +93,11 @@
 
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @FlakyTest
     @Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index 33626d0..c706428 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.FlakyTest
@@ -26,7 +27,11 @@
 import com.android.server.wm.flicker.LAUNCHER_COMPONENT
 import com.android.server.wm.flicker.annotation.Group3
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import com.android.server.wm.flicker.rules.WMFlickerServiceRuleForTestSpec
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
+import org.junit.Rule
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
@@ -55,6 +60,9 @@
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @Group3
 class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
+    @get:Rule
+    val flickerRule = WMFlickerServiceRuleForTestSpec(testSpec)
+
     /**
      * Defines the transition used to run the test
      */
@@ -65,6 +73,33 @@
             }
         }
 
+    @Postsubmit
+    @Test
+    fun runPresubmitAssertion() {
+        flickerRule.checkPresubmitAssertions()
+    }
+
+    @Postsubmit
+    @Test
+    fun runPostsubmitAssertion() {
+        flickerRule.checkPostsubmitAssertions()
+    }
+
+    @FlakyTest
+    @Test
+    fun runFlakyAssertion() {
+        flickerRule.checkFlakyAssertions()
+    }
+
+    /** {@inheritDoc}  */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     /**
      * Checks [pipApp] window remains visible throughout the animation
      */
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index 791505b..f923a23 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -27,6 +27,7 @@
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.entireScreenCovered
 import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.traces.common.FlickerComponentName
@@ -35,6 +36,7 @@
 import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_PORTRAIT
 import com.android.wm.shell.flicker.testapp.Components.PipActivity.ACTION_ENTER_PIP
 import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -119,7 +121,11 @@
      */
     @Presubmit
     @Test
-    override fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     /**
      * Checks that all parts of the screen are covered at the start and end of the transition
@@ -204,6 +210,7 @@
     @Presubmit
     @Test
     fun testAppPlusPipLayerCoversFullScreenOnEnd() {
+        // This test doesn't work in shell transitions because of b/206669574
         testSpec.assertLayersEnd {
             val pipRegion = visibleRegion(pipApp.component).region
             visibleRegion(testApp.component)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
index 8267442..3e7e2f5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
@@ -18,7 +18,9 @@
 
 import android.platform.test.annotations.Presubmit
 import com.android.server.wm.flicker.FlickerTestParameter
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.wm.shell.flicker.helpers.FixedAppHelper
+import org.junit.Assume.assumeFalse
 import org.junit.Test
 
 /**
@@ -27,6 +29,15 @@
 abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
     protected val testApp = FixedAppHelper(instrumentation)
 
+    /** {@inheritDoc}  */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     /**
      * Checks that the pip app window remains inside the display bounds throughout the whole
      * animation
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
index 5f29dbc..4d63d14 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -23,7 +24,10 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group3
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -75,6 +79,15 @@
             }
         }
 
+    /** {@inheritDoc}  */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
index 00ccf26..34c0f849 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
@@ -16,14 +16,22 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group3
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import com.android.server.wm.flicker.rules.WMFlickerServiceRuleForTestSpec
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
+import org.junit.Rule
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -52,6 +60,8 @@
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @Group3
 class ExitPipViaIntentTest(testSpec: FlickerTestParameter) : ExitPipToAppTransition(testSpec) {
+    @get:Rule
+    val flickerRule = WMFlickerServiceRuleForTestSpec(testSpec)
 
     /**
      * Defines the transition used to run the test
@@ -72,6 +82,33 @@
             }
         }
 
+    @Postsubmit
+    @Test
+    fun runPresubmitAssertion() {
+        flickerRule.checkPresubmitAssertions()
+    }
+
+    @Postsubmit
+    @Test
+    fun runPostsubmitAssertion() {
+        flickerRule.checkPostsubmitAssertions()
+    }
+
+    @FlakyTest
+    @Test
+    fun runFlakyAssertion() {
+        flickerRule.checkFlakyAssertions()
+    }
+
+    /** {@inheritDoc}  */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
index b0b11e9..1b7220e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
@@ -16,14 +16,23 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
 import com.android.server.wm.flicker.FlickerTestParameter
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group3
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import com.android.server.wm.flicker.rules.WMFlickerServiceRuleForTestSpec
+import org.junit.Assume.assumeFalse
+import org.junit.Before
 import org.junit.FixMethodOrder
+import org.junit.Rule
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -52,6 +61,9 @@
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @Group3
 class ExitPipWithDismissButtonTest(testSpec: FlickerTestParameter) : ExitPipTransition(testSpec) {
+    @get:Rule
+    val flickerRule = WMFlickerServiceRuleForTestSpec(testSpec)
+
     override val transition: FlickerBuilder.() -> Unit
         get() = {
             super.transition(this)
@@ -60,6 +72,39 @@
             }
         }
 
+    @Postsubmit
+    @Test
+    fun runPresubmitAssertion() {
+        flickerRule.checkPresubmitAssertions()
+    }
+
+    @Postsubmit
+    @Test
+    fun runPostsubmitAssertion() {
+        flickerRule.checkPostsubmitAssertions()
+    }
+
+    @FlakyTest
+    @Test
+    fun runFlakyAssertion() {
+        flickerRule.checkFlakyAssertions()
+    }
+
+    @Before
+    fun onBefore() {
+        // This CUJ don't work in shell transitions because of b/204570898 b/204562589
+        assumeFalse(isShellTransitionsEnabled)
+    }
+
+    /** {@inheritDoc}  */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
index f4eb701..40be21a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
@@ -25,7 +25,9 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group3
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -70,22 +72,6 @@
             }
         }
 
-    @Presubmit
-    @Test
-    override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
-
-    @Presubmit
-    @Test
-    override fun statusBarLayerIsVisible() = super.statusBarLayerIsVisible()
-
-    @Presubmit
-    @Test
-    override fun navBarWindowIsVisible() = super.navBarWindowIsVisible()
-
-    @Presubmit
-    @Test
-    override fun statusBarWindowIsVisible() = super.statusBarWindowIsVisible()
-
     @FlakyTest
     @Test
     override fun pipWindowBecomesInvisible() = super.pipWindowBecomesInvisible()
@@ -96,15 +82,11 @@
 
     @Presubmit
     @Test
-    override fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
-
-    @Presubmit
-    @Test
-    override fun entireScreenCovered() = super.entireScreenCovered()
-
-    @Presubmit
-    @Test
-    override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     companion object {
         /**
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
index f196764..3511cc2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExpandPipOnDoubleClickTest.kt
@@ -26,6 +26,9 @@
 import com.android.server.wm.flicker.LAUNCHER_COMPONENT
 import com.android.server.wm.flicker.annotation.Group3
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
+import org.junit.Before
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -62,6 +65,12 @@
             }
         }
 
+    @Before
+    fun onBefore() {
+        // This CUJ don't work in shell transitions because of b/204570898 b/204562589
+        assumeFalse(isShellTransitionsEnabled)
+    }
+
     /**
      * Checks that the pip app window remains inside the display bounds throughout the whole
      * animation
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt
index d9685f3..10a542f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -23,8 +24,11 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group3
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.traces.RegionSubject
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -78,6 +82,15 @@
         current.isHigherOrEqual(previous.region)
     }
 
+    /** {@inheritDoc}  */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt
index c6b42ea..cb6ba0e6 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipUpShelfHeightChangeTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -23,8 +24,11 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group3
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.traces.RegionSubject
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
+import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.MethodSorters
 import org.junit.runners.Parameterized
@@ -78,6 +82,15 @@
         current.isLowerOrEqual(previous.region)
     }
 
+    /** {@inheritDoc}  */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index 45cbdc8..81ac10f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -25,9 +25,11 @@
 import com.android.server.wm.flicker.annotation.Group4
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.traces.common.FlickerComponentName
 import com.android.wm.shell.flicker.helpers.ImeAppHelper
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -70,6 +72,15 @@
             }
         }
 
+    /** {@inheritDoc}  */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     /**
      * Ensure the pip window remains visible throughout any keyboard interactions
      */
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index 3e3ea16..70075dd 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -89,6 +89,15 @@
             }
         }
 
+    /** {@inheritDoc}  */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(com.android.server.wm.flicker.helpers.isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
     @FlakyTest(bugId = 161435597)
     @Test
     fun pipWindowInsideDisplayBounds() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index af984b3..16fc048 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -27,10 +27,13 @@
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.entireScreenCovered
 import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.wm.shell.flicker.helpers.FixedAppHelper
+import org.junit.Assume.assumeFalse
+import org.junit.Before
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -81,6 +84,12 @@
             }
         }
 
+    @Before
+    fun onBefore() {
+        // This CUJ don't work in shell transitions because of b/204570898 b/204562589 b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+    }
+
     /**
      * Checks that all parts of the screen are covered at the start and end of the transition
      */
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
index f8e2d38..a940a7f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.flicker.pip
 
+import android.platform.test.annotations.Postsubmit
 import android.view.Surface
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
@@ -25,10 +26,12 @@
 import com.android.server.wm.flicker.annotation.Group4
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.WindowUtils
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
 import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
 import com.android.wm.shell.flicker.testapp.Components.PipActivity.EXTRA_ENTER_PIP
 import org.junit.Assert.assertEquals
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -80,19 +83,19 @@
             }
         }
 
-    @FlakyTest
+    @Postsubmit
     @Test
     override fun navBarLayerIsVisible() = super.navBarLayerIsVisible()
 
-    @FlakyTest
+    @Postsubmit
     @Test
     override fun navBarWindowIsVisible() = super.navBarWindowIsVisible()
 
-    @FlakyTest
+    @Postsubmit
     @Test
     override fun statusBarLayerIsVisible() = super.statusBarLayerIsVisible()
 
-    @FlakyTest
+    @Postsubmit
     @Test
     override fun statusBarWindowIsVisible() = super.statusBarWindowIsVisible()
 
@@ -100,11 +103,15 @@
     @Test
     override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
 
-    @FlakyTest
+    @Postsubmit
     @Test
-    override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
 
-    @FlakyTest
+    @Postsubmit
     @Test
     fun pipWindowInsideDisplay() {
         testSpec.assertWmStart {
@@ -112,7 +119,7 @@
         }
     }
 
-    @FlakyTest
+    @Postsubmit
     @Test
     fun pipAppShowsOnTop() {
         testSpec.assertWmEnd {
@@ -120,7 +127,7 @@
         }
     }
 
-    @FlakyTest
+    @Postsubmit
     @Test
     fun pipLayerInsideDisplay() {
         testSpec.assertLayersStart {
@@ -128,13 +135,13 @@
         }
     }
 
-    @FlakyTest
+    @Postsubmit
     @Test
     fun pipAlwaysVisible() = testSpec.assertWm {
         this.isAppWindowVisible(pipApp.component)
     }
 
-    @FlakyTest
+    @Postsubmit
     @Test
     fun pipAppLayerCoversFullScreen() {
         testSpec.assertLayersEnd {
@@ -142,7 +149,7 @@
         }
     }
 
-    @FlakyTest
+    @Postsubmit
     @Test
     override fun entireScreenCovered() = super.entireScreenCovered()
 
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
index 31e9167..9c3b0fa 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
@@ -27,7 +27,7 @@
 import com.android.wm.shell.flicker.pip.PipTestBase
 import org.junit.After
 import org.junit.Assert.assertFalse
-import org.junit.Assume
+import org.junit.Assume.assumeTrue
 import org.junit.Before
 
 abstract class TvPipTestBase : PipTestBase(rotationToString(ROTATION_0), ROTATION_0) {
@@ -37,7 +37,7 @@
     @Before
     final override fun televisionSetUp() {
         // Should run only on TVs.
-        Assume.assumeTrue(isTelevision)
+        assumeTrue(isTelevision)
 
         systemUiProcessObserver.start()
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index 73eebad..453050f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -106,6 +106,12 @@
     }
 
     @Test
+    public void testSetDivideRatio() {
+        mSplitLayout.setDivideRatio(0.5f);
+        verify(mSplitLayoutHandler).onLayoutSizeChanged(any(SplitLayout.class));
+    }
+
+    @Test
     public void testOnDoubleTappedDivider() {
         mSplitLayout.onDoubleTappedDivider();
         verify(mSplitLayoutHandler).onDoubleTappedDivider();
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.java
new file mode 100644
index 0000000..bfa2c92
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/draganddrop/DragAndDropControllerTest.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.wm.shell.draganddrop;
+
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.view.Display;
+import android.view.DragEvent;
+import android.view.View;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.wm.shell.common.DisplayController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for the drag and drop controller.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DragAndDropControllerTest {
+
+    @Mock
+    private Context mContext;
+
+    @Mock
+    private DisplayController mDisplayController;
+
+    @Mock
+    private UiEventLogger mUiEventLogger;
+
+    private DragAndDropController mController;
+
+    @Before
+    public void setUp() throws RemoteException {
+        MockitoAnnotations.initMocks(this);
+
+        mController = new DragAndDropController(mContext, mDisplayController, mUiEventLogger);
+    }
+
+    @Test
+    public void testIgnoreNonDefaultDisplays() {
+        final int nonDefaultDisplayId = 12345;
+        final View dragLayout = mock(View.class);
+        final Display display = mock(Display.class);
+        doReturn(nonDefaultDisplayId).when(display).getDisplayId();
+        doReturn(display).when(dragLayout).getDisplay();
+
+        // Expect no per-display layout to be added
+        mController.onDisplayAdded(nonDefaultDisplayId);
+        assertFalse(mController.onDrag(dragLayout, mock(DragEvent.class)));
+    }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
index c2f58b8..935f669 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java
@@ -191,7 +191,7 @@
         mPipController.mDisplaysChangedListener.onDisplayConfigurationChanged(
                 displayId, new Configuration());
 
-        verify(mMockPipMotionHelper).animateResizedBounds(any(Rect.class));
+        verify(mMockPipMotionHelper).movePip(any(Rect.class));
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
index 19a5417..50f6bd7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
@@ -28,6 +28,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import static java.lang.Integer.MAX_VALUE;
@@ -83,6 +84,36 @@
     }
 
     @Test
+    public void testAddRemoveSplitNotifyChange() {
+        ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
+        ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
+        setRawList(t1, t2);
+
+        mRecentTasksController.addSplitPair(t1.taskId, t2.taskId, mock(StagedSplitBounds.class));
+        verify(mRecentTasksController).notifyRecentTasksChanged();
+
+        reset(mRecentTasksController);
+        mRecentTasksController.removeSplitPair(t1.taskId);
+        verify(mRecentTasksController).notifyRecentTasksChanged();
+    }
+
+    @Test
+    public void testAddSameSplitBoundsInfoSkipNotifyChange() {
+        ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
+        ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
+        setRawList(t1, t2);
+
+        // Verify only one update if the split info is the same
+        StagedSplitBounds bounds1 = new StagedSplitBounds(new Rect(0, 0, 50, 50),
+                new Rect(50, 50, 100, 100), t1.taskId, t2.taskId);
+        mRecentTasksController.addSplitPair(t1.taskId, t2.taskId, bounds1);
+        StagedSplitBounds bounds2 = new StagedSplitBounds(new Rect(0, 0, 50, 50),
+                new Rect(50, 50, 100, 100), t1.taskId, t2.taskId);
+        mRecentTasksController.addSplitPair(t1.taskId, t2.taskId, bounds2);
+        verify(mRecentTasksController, times(1)).notifyRecentTasksChanged();
+    }
+
+    @Test
     public void testGetRecentTasks() {
         ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1);
         ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java
index d12cf5c..877b192 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java
@@ -26,6 +26,7 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
@@ -43,6 +44,7 @@
 import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener;
 import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.SyncTransactionQueue;
 
 import org.junit.Before;
@@ -72,6 +74,7 @@
     private @Mock DisplayImeController mMockImeController;
     private @Mock ShellTaskOrganizer.TaskListener mMockTaskListener;
     private @Mock SyncTransactionQueue mMockSyncQueue;
+    private @Mock ShellExecutor mMockExecutor;
     private @Mock SizeCompatUILayout mMockLayout;
 
     @Captor
@@ -85,7 +88,7 @@
         doReturn(DISPLAY_ID).when(mMockLayout).getDisplayId();
         doReturn(TASK_ID).when(mMockLayout).getTaskId();
         mController = new SizeCompatUIController(mContext, mMockDisplayController,
-                mMockDisplayInsetsController, mMockImeController, mMockSyncQueue) {
+                mMockDisplayInsetsController, mMockImeController, mMockSyncQueue, mMockExecutor) {
             @Override
             SizeCompatUILayout createLayout(Context context, int displayId, int taskId,
                     Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener) {
@@ -106,19 +109,17 @@
         final Configuration taskConfig = new Configuration();
 
         // Verify that the restart button is added with non-null size compat info.
-        mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
-                mMockTaskListener);
+        mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener);
 
         verify(mController).createLayout(any(), eq(DISPLAY_ID), eq(TASK_ID), eq(taskConfig),
                 eq(mMockTaskListener));
 
         // Verify that the restart button is updated with non-null new size compat info.
         final Configuration newTaskConfig = new Configuration();
-        mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig,
-                mMockTaskListener);
+        mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig, mMockTaskListener);
 
         verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener,
-                false /* isImeShowing */);
+                true /* show */);
 
         // Verify that the restart button is removed with null size compat info.
         mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, null, mMockTaskListener);
@@ -196,15 +197,90 @@
     @Test
     public void testChangeButtonVisibilityOnImeShowHide() {
         final Configuration taskConfig = new Configuration();
-        mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig,
-                mMockTaskListener);
+        mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener);
 
+        // Verify that the restart button is hidden after IME is showing.
         mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */);
 
-        verify(mMockLayout).updateImeVisibility(true);
+        verify(mMockLayout).updateVisibility(false);
 
+        // Verify button remains hidden while IME is showing.
+        mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener);
+
+        verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener,
+                false /* show */);
+
+        // Verify button is shown after IME is hidden.
         mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */);
 
-        verify(mMockLayout).updateImeVisibility(false);
+        verify(mMockLayout).updateVisibility(true);
+    }
+
+    @Test
+    public void testChangeButtonVisibilityOnKeyguardOccludedChanged() {
+        final Configuration taskConfig = new Configuration();
+        mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener);
+
+        // Verify that the restart button is hidden after keyguard becomes occluded.
+        mController.onKeyguardOccludedChanged(true);
+
+        verify(mMockLayout).updateVisibility(false);
+
+        // Verify button remains hidden while keyguard is occluded.
+        mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener);
+
+        verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener,
+                false /* show */);
+
+        // Verify button is shown after keyguard becomes not occluded.
+        mController.onKeyguardOccludedChanged(false);
+
+        verify(mMockLayout).updateVisibility(true);
+    }
+
+    @Test
+    public void testButtonRemainsHiddenOnKeyguardOccludedFalseWhenImeIsShowing() {
+        final Configuration taskConfig = new Configuration();
+        mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener);
+
+        mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */);
+        mController.onKeyguardOccludedChanged(true);
+
+        verify(mMockLayout, times(2)).updateVisibility(false);
+
+        clearInvocations(mMockLayout);
+
+        // Verify button remains hidden after keyguard becomes not occluded since IME is showing.
+        mController.onKeyguardOccludedChanged(false);
+
+        verify(mMockLayout).updateVisibility(false);
+
+        // Verify button is shown after IME is not showing.
+        mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */);
+
+        verify(mMockLayout).updateVisibility(true);
+    }
+
+    @Test
+    public void testButtonRemainsHiddenOnImeHideWhenKeyguardIsOccluded() {
+        final Configuration taskConfig = new Configuration();
+        mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener);
+
+        mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */);
+        mController.onKeyguardOccludedChanged(true);
+
+        verify(mMockLayout, times(2)).updateVisibility(false);
+
+        clearInvocations(mMockLayout);
+
+        // Verify button remains hidden after IME is hidden since keyguard is occluded.
+        mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */);
+
+        verify(mMockLayout).updateVisibility(false);
+
+        // Verify button is shown after keyguard becomes not occluded.
+        mController.onKeyguardOccludedChanged(false);
+
+        verify(mMockLayout).updateVisibility(true);
     }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
index 2ba603c..eb9305b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
@@ -96,8 +96,8 @@
 
     @Test
     public void testCreateSizeCompatButton() {
-        // Not create button if IME is showing.
-        mLayout.createSizeCompatButton(true /* isImeShowing */);
+        // Not create button if show is false.
+        mLayout.createSizeCompatButton(false /* show */);
 
         verify(mLayout.mButtonWindowManager, never()).createSizeCompatButton();
         assertNull(mLayout.mButton);
@@ -106,7 +106,7 @@
 
         // Not create hint popup.
         mLayout.mShouldShowHint = false;
-        mLayout.createSizeCompatButton(false /* isImeShowing */);
+        mLayout.createSizeCompatButton(true /* show */);
 
         verify(mLayout.mButtonWindowManager).createSizeCompatButton();
         assertNotNull(mLayout.mButton);
@@ -116,7 +116,7 @@
         // Create hint popup.
         mLayout.release();
         mLayout.mShouldShowHint = true;
-        mLayout.createSizeCompatButton(false /* isImeShowing */);
+        mLayout.createSizeCompatButton(true /* show */);
 
         verify(mLayout.mButtonWindowManager, times(2)).createSizeCompatButton();
         assertNotNull(mLayout.mButton);
@@ -128,7 +128,7 @@
 
     @Test
     public void testRelease() {
-        mLayout.createSizeCompatButton(false /* isImeShowing */);
+        mLayout.createSizeCompatButton(true /* show */);
         final SizeCompatUIWindowManager hintWindowManager = mLayout.mHintWindowManager;
 
         mLayout.release();
@@ -142,12 +142,11 @@
 
     @Test
     public void testUpdateSizeCompatInfo() {
-        mLayout.createSizeCompatButton(false /* isImeShowing */);
+        mLayout.createSizeCompatButton(true /* show */);
 
         // No diff
         clearInvocations(mLayout);
-        mLayout.updateSizeCompatInfo(mTaskConfig, mTaskListener,
-                false /* isImeShowing */);
+        mLayout.updateSizeCompatInfo(mTaskConfig, mTaskListener, true /* show */);
 
         verify(mLayout, never()).updateButtonSurfacePosition();
         verify(mLayout, never()).release();
@@ -158,7 +157,7 @@
         final ShellTaskOrganizer.TaskListener newTaskListener = mock(
                 ShellTaskOrganizer.TaskListener.class);
         mLayout.updateSizeCompatInfo(mTaskConfig, newTaskListener,
-                false /* isImeShowing */);
+                true /* show */);
 
         verify(mLayout).release();
         verify(mLayout).createSizeCompatButton(anyBoolean());
@@ -168,7 +167,7 @@
         final Configuration newTaskConfiguration = new Configuration();
         newTaskConfiguration.windowConfiguration.setBounds(new Rect(0, 1000, 0, 2000));
         mLayout.updateSizeCompatInfo(newTaskConfiguration, newTaskListener,
-                false /* isImeShowing */);
+                true /* show */);
 
         verify(mLayout).updateButtonSurfacePosition();
         verify(mLayout).updateHintSurfacePosition();
@@ -220,24 +219,24 @@
     }
 
     @Test
-    public void testUpdateImeVisibility() {
+    public void testUpdateVisibility() {
         // Create button if it is not created.
         mLayout.mButton = null;
-        mLayout.updateImeVisibility(false /* isImeShowing */);
+        mLayout.updateVisibility(true /* show */);
 
-        verify(mLayout).createSizeCompatButton(false /* isImeShowing */);
+        verify(mLayout).createSizeCompatButton(true /* show */);
 
-        // Hide button if ime is shown.
+        // Hide button.
         clearInvocations(mLayout);
         doReturn(View.VISIBLE).when(mButton).getVisibility();
-        mLayout.updateImeVisibility(true /* isImeShowing */);
+        mLayout.updateVisibility(false /* show */);
 
         verify(mLayout, never()).createSizeCompatButton(anyBoolean());
         verify(mButton).setVisibility(View.GONE);
 
-        // Show button if ime is not shown.
+        // Show button.
         doReturn(View.GONE).when(mButton).getVisibility();
-        mLayout.updateImeVisibility(false /* isImeShowing */);
+        mLayout.updateVisibility(true /* show */);
 
         verify(mLayout, never()).createSizeCompatButton(anyBoolean());
         verify(mButton).setVisibility(View.VISIBLE);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index ad65c04..ef14d84 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -19,11 +19,14 @@
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
 import static android.view.Display.DEFAULT_DISPLAY;
 
-import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME;
 import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.wm.shell.common.split.SplitLayout.SPLIT_POSITION_TOP_OR_LEFT;
+import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_MAIN;
+import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_SIDE;
+import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_RETURN_HOME;
 
+import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
@@ -49,7 +52,6 @@
 import com.android.wm.shell.common.SyncTransactionQueue;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.common.split.SplitLayout;
-import com.android.wm.shell.recents.RecentTasksController;
 import com.android.wm.shell.transition.Transitions;
 
 import org.junit.Before;
@@ -110,12 +112,39 @@
     }
 
     @Test
-    public void testMoveToSideStage() {
+    public void testMoveToStage() {
         final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
 
-        mStageCoordinator.moveToSideStage(task, SPLIT_POSITION_BOTTOM_OR_RIGHT);
+        mStageCoordinator.moveToStage(task, STAGE_TYPE_MAIN, SPLIT_POSITION_BOTTOM_OR_RIGHT,
+                new WindowContainerTransaction());
+        verify(mMainStage).addTask(eq(task), any(WindowContainerTransaction.class));
+        assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getMainStagePosition());
 
+        mStageCoordinator.moveToStage(task, STAGE_TYPE_SIDE, SPLIT_POSITION_BOTTOM_OR_RIGHT,
+                new WindowContainerTransaction());
         verify(mSideStage).addTask(eq(task), any(WindowContainerTransaction.class));
+        assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
+    }
+
+    @Test
+    public void testMoveToUndefinedStage() {
+        final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
+
+        // Verify move to undefined stage while split screen not activated moves task to side stage.
+        when(mMainStage.isActive()).thenReturn(false);
+        mStageCoordinator.setSideStagePosition(SPLIT_POSITION_TOP_OR_LEFT, null);
+        mStageCoordinator.moveToStage(task, STAGE_TYPE_UNDEFINED, SPLIT_POSITION_BOTTOM_OR_RIGHT,
+                new WindowContainerTransaction());
+        verify(mSideStage).addTask(eq(task), any(WindowContainerTransaction.class));
+        assertEquals(SPLIT_POSITION_BOTTOM_OR_RIGHT, mStageCoordinator.getSideStagePosition());
+
+        // Verify move to undefined stage after split screen activated moves task based on position.
+        when(mMainStage.isActive()).thenReturn(true);
+        assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition());
+        mStageCoordinator.moveToStage(task, STAGE_TYPE_UNDEFINED, SPLIT_POSITION_TOP_OR_LEFT,
+                new WindowContainerTransaction());
+        verify(mMainStage).addTask(eq(task), any(WindowContainerTransaction.class));
+        assertEquals(SPLIT_POSITION_TOP_OR_LEFT, mStageCoordinator.getMainStagePosition());
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index 70b7c67..d92b12e 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -31,6 +31,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -117,16 +118,19 @@
                 WindowManager.LayoutParams params, int suggestType) {
             // listen for addView
             mAddWindowForTask = taskId;
+            saveSplashScreenRecord(appToken, taskId, view, suggestType);
             // Do not wait for background color
             return false;
         }
 
         @Override
-        protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo) {
+        protected void removeWindowSynced(StartingWindowRemovalInfo removalInfo,
+                boolean immediately) {
             // listen for removeView
             if (mAddWindowForTask == removalInfo.taskId) {
                 mAddWindowForTask = 0;
             }
+            mStartingWindowRecords.remove(removalInfo.taskId);
         }
     }
 
@@ -179,7 +183,7 @@
         removalInfo.taskId = windowInfo.taskInfo.taskId;
         mStartingSurfaceDrawer.removeStartingWindow(removalInfo);
         waitHandlerIdle(mTestHandler);
-        verify(mStartingSurfaceDrawer).removeWindowSynced(any());
+        verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(false));
         assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, 0);
     }
 
@@ -267,11 +271,32 @@
 
             // Verify the task snapshot with IME snapshot will be removed when received the real IME
             // drawn callback.
+            // makeTaskSnapshotWindow shall call removeWindowSynced before there add a new
+            // StartingWindowRecord for the task.
             mStartingSurfaceDrawer.onImeDrawnOnTask(1);
-            verify(mockSnapshotWindow).removeImmediately();
+            verify(mStartingSurfaceDrawer, times(2))
+                    .removeWindowSynced(any(), eq(true));
         }
     }
 
+    @Test
+    public void testClearAllWindows() {
+        final int taskId = 1;
+        final StartingWindowInfo windowInfo =
+                createWindowInfo(taskId, android.R.style.Theme);
+        mStartingSurfaceDrawer.addSplashScreenStartingWindow(windowInfo, mBinder,
+                STARTING_WINDOW_TYPE_SPLASH_SCREEN);
+        waitHandlerIdle(mTestHandler);
+        verify(mStartingSurfaceDrawer).addWindow(eq(taskId), eq(mBinder), any(), any(), any(),
+                eq(STARTING_WINDOW_TYPE_SPLASH_SCREEN));
+        assertEquals(mStartingSurfaceDrawer.mAddWindowForTask, taskId);
+
+        mStartingSurfaceDrawer.clearAllWindows();
+        waitHandlerIdle(mTestHandler);
+        verify(mStartingSurfaceDrawer).removeWindowSynced(any(), eq(true));
+        assertEquals(mStartingSurfaceDrawer.mStartingWindowRecords.size(), 0);
+    }
+
     private StartingWindowInfo createWindowInfo(int taskId, int themeResId) {
         StartingWindowInfo windowInfo = new StartingWindowInfo();
         final ActivityInfo info = new ActivityInfo();
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 491f5f5..a2d0103 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -107,6 +107,8 @@
     target: {
         android: {
             shared_libs: [
+                "android.hardware.graphics.common-V3-ndk",
+                "android.hardware.graphics.common@1.2",
                 "liblog",
                 "libcutils",
                 "libutils",
@@ -126,9 +128,11 @@
             static_libs: [
                 "libEGL_blobCache",
                 "libprotoutil",
+                "libshaders",
                 "libstatslog_hwui",
                 "libstatspull_lazy",
                 "libstatssocket_lazy",
+                "libtonemap",
             ],
         },
         host: {
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 0b3b393..a5c0924 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -20,9 +20,11 @@
 
 // TODO: Use public SurfaceTexture APIs once available and include public NDK header file instead.
 #include <surfacetexture/surface_texture_platform.h>
+
 #include "AutoBackendTextureRelease.h"
 #include "Matrix.h"
 #include "Properties.h"
+#include "android/hdr_metadata.h"
 #include "renderstate/RenderState.h"
 #include "renderthread/EglManager.h"
 #include "renderthread/RenderThread.h"
@@ -147,6 +149,9 @@
             mUpdateTexImage = false;
             float transformMatrix[16];
             android_dataspace dataspace;
+            AHdrMetadataType hdrMetadataType;
+            android_cta861_3_metadata cta861_3;
+            android_smpte2086_metadata smpte2086;
             int slot;
             bool newContent = false;
             ARect currentCrop;
@@ -155,8 +160,9 @@
             // is necessary if the SurfaceTexture queue is in synchronous mode, and we
             // cannot tell which mode it is in.
             AHardwareBuffer* hardwareBuffer = ASurfaceTexture_dequeueBuffer(
-                    mSurfaceTexture.get(), &slot, &dataspace, transformMatrix, &outTransform,
-                    &newContent, createReleaseFence, fenceWait, this, &currentCrop);
+                    mSurfaceTexture.get(), &slot, &dataspace, &hdrMetadataType, &cta861_3,
+                    &smpte2086, transformMatrix, &outTransform, &newContent, createReleaseFence,
+                    fenceWait, this, &currentCrop);
 
             if (hardwareBuffer) {
                 mCurrentSlot = slot;
@@ -173,7 +179,18 @@
                     SkRect currentCropRect =
                             SkRect::MakeLTRB(currentCrop.left, currentCrop.top, currentCrop.right,
                                              currentCrop.bottom);
-                    updateLayer(forceFilter, layerImage, outTransform, currentCropRect);
+
+                    float maxLuminanceNits = -1.f;
+                    if (hdrMetadataType & HDR10_SMPTE2086) {
+                        maxLuminanceNits = std::max(smpte2086.maxLuminance, maxLuminanceNits);
+                    }
+
+                    if (hdrMetadataType & HDR10_CTA861_3) {
+                        maxLuminanceNits =
+                                std::max(cta861_3.maxContentLightLevel, maxLuminanceNits);
+                    }
+                    updateLayer(forceFilter, layerImage, outTransform, currentCropRect,
+                                maxLuminanceNits);
                 }
             }
         }
@@ -186,13 +203,15 @@
 }
 
 void DeferredLayerUpdater::updateLayer(bool forceFilter, const sk_sp<SkImage>& layerImage,
-                                       const uint32_t transform, SkRect currentCrop) {
+                                       const uint32_t transform, SkRect currentCrop,
+                                       float maxLuminanceNits) {
     mLayer->setBlend(mBlend);
     mLayer->setForceFilter(forceFilter);
     mLayer->setSize(mWidth, mHeight);
     mLayer->setCurrentCropRect(currentCrop);
     mLayer->setWindowTransform(transform);
     mLayer->setImage(layerImage);
+    mLayer->setMaxLuminanceNits(maxLuminanceNits);
 }
 
 void DeferredLayerUpdater::detachSurfaceTexture() {
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index da8041f..9a4c550 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -91,7 +91,7 @@
     void detachSurfaceTexture();
 
     void updateLayer(bool forceFilter, const sk_sp<SkImage>& layerImage, const uint32_t transform,
-                     SkRect currentCrop);
+                     SkRect currentCrop, float maxLuminanceNits = -1.f);
 
     void destroyLayer();
 
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 0789344..47eb5d3 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -96,6 +96,12 @@
 
     inline sk_sp<SkImage> getImage() const { return this->layerImage; }
 
+    inline void setMaxLuminanceNits(float maxLuminanceNits) {
+        mMaxLuminanceNits = maxLuminanceNits;
+    }
+
+    inline float getMaxLuminanceNits() { return mMaxLuminanceNits; }
+
     void draw(SkCanvas* canvas);
 
 protected:
@@ -158,6 +164,11 @@
      */
     bool mBlend = false;
 
+    /**
+     * Max input luminance if the layer is HDR
+     */
+    float mMaxLuminanceNits = -1;
+
 };  // struct Layer
 
 }  // namespace uirenderer
diff --git a/libs/hwui/WebViewFunctorManager.cpp b/libs/hwui/WebViewFunctorManager.cpp
index 5aad821..6fc251d 100644
--- a/libs/hwui/WebViewFunctorManager.cpp
+++ b/libs/hwui/WebViewFunctorManager.cpp
@@ -118,6 +118,24 @@
     }
 }
 
+bool WebViewFunctor::prepareRootSurfaceControl() {
+    if (!Properties::enableWebViewOverlays) return false;
+
+    renderthread::CanvasContext* activeContext = renderthread::CanvasContext::getActiveContext();
+    if (!activeContext) return false;
+
+    ASurfaceControl* rootSurfaceControl = activeContext->getSurfaceControl();
+    if (!rootSurfaceControl) return false;
+
+    int32_t rgid = activeContext->getSurfaceControlGenerationId();
+    if (mParentSurfaceControlGenerationId != rgid) {
+        reparentSurfaceControl(rootSurfaceControl);
+        mParentSurfaceControlGenerationId = rgid;
+    }
+
+    return true;
+}
+
 void WebViewFunctor::drawGl(const DrawGlInfo& drawInfo) {
     ATRACE_NAME("WebViewFunctor::drawGl");
     if (!mHasContext) {
@@ -131,20 +149,8 @@
             .mergeTransaction = currentFunctor.mergeTransaction,
     };
 
-    if (Properties::enableWebViewOverlays && !drawInfo.isLayer) {
-        renderthread::CanvasContext* activeContext =
-                renderthread::CanvasContext::getActiveContext();
-        if (activeContext != nullptr) {
-            ASurfaceControl* rootSurfaceControl = activeContext->getSurfaceControl();
-            if (rootSurfaceControl) {
-                overlayParams.overlaysMode = OverlaysMode::Enabled;
-                int32_t rgid = activeContext->getSurfaceControlGenerationId();
-                if (mParentSurfaceControlGenerationId != rgid) {
-                    reparentSurfaceControl(rootSurfaceControl);
-                    mParentSurfaceControlGenerationId = rgid;
-                }
-            }
-        }
+    if (!drawInfo.isLayer && prepareRootSurfaceControl()) {
+        overlayParams.overlaysMode = OverlaysMode::Enabled;
     }
 
     mCallbacks.gles.draw(mFunctor, mData, drawInfo, overlayParams);
@@ -170,7 +176,10 @@
             .mergeTransaction = currentFunctor.mergeTransaction,
     };
 
-    // TODO, enable surface control once offscreen mode figured out
+    if (!params.is_layer && prepareRootSurfaceControl()) {
+        overlayParams.overlaysMode = OverlaysMode::Enabled;
+    }
+
     mCallbacks.vk.draw(mFunctor, mData, params, overlayParams);
 }
 
diff --git a/libs/hwui/WebViewFunctorManager.h b/libs/hwui/WebViewFunctorManager.h
index f28f310..0a02f2d 100644
--- a/libs/hwui/WebViewFunctorManager.h
+++ b/libs/hwui/WebViewFunctorManager.h
@@ -88,6 +88,7 @@
     }
 
 private:
+    bool prepareRootSurfaceControl();
     void reparentSurfaceControl(ASurfaceControl* parent);
 
 private:
diff --git a/libs/hwui/jni/text/MeasuredText.cpp b/libs/hwui/jni/text/MeasuredText.cpp
index 7793746..bd9bd71 100644
--- a/libs/hwui/jni/text/MeasuredText.cpp
+++ b/libs/hwui/jni/text/MeasuredText.cpp
@@ -80,15 +80,17 @@
 }
 
 // Regular JNI
-static jlong nBuildMeasuredText(JNIEnv* env, jclass /* unused */, jlong builderPtr,
-                                jlong hintPtr, jcharArray javaText, jboolean computeHyphenation,
-                                jboolean computeLayout) {
+static jlong nBuildMeasuredText(JNIEnv* env, jclass /* unused */, jlong builderPtr, jlong hintPtr,
+                                jcharArray javaText, jboolean computeHyphenation,
+                                jboolean computeLayout, jboolean fastHyphenationMode) {
     ScopedCharArrayRO text(env, javaText);
     const minikin::U16StringPiece textBuffer(text.get(), text.size());
 
     // Pass the ownership to Java.
-    return toJLong(toBuilder(builderPtr)->build(textBuffer, computeHyphenation, computeLayout,
-                                                toMeasuredParagraph(hintPtr)).release());
+    return toJLong(toBuilder(builderPtr)
+                           ->build(textBuffer, computeHyphenation, computeLayout,
+                                   fastHyphenationMode, toMeasuredParagraph(hintPtr))
+                           .release());
 }
 
 // Regular JNI
@@ -140,12 +142,12 @@
 }
 
 static const JNINativeMethod gMTBuilderMethods[] = {
-    // MeasuredParagraphBuilder native functions.
-    {"nInitBuilder", "()J", (void*) nInitBuilder},
-    {"nAddStyleRun", "(JJIIZ)V", (void*) nAddStyleRun},
-    {"nAddReplacementRun", "(JJIIF)V", (void*) nAddReplacementRun},
-    {"nBuildMeasuredText", "(JJ[CZZ)J", (void*) nBuildMeasuredText},
-    {"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
+        // MeasuredParagraphBuilder native functions.
+        {"nInitBuilder", "()J", (void*)nInitBuilder},
+        {"nAddStyleRun", "(JJIIZ)V", (void*)nAddStyleRun},
+        {"nAddReplacementRun", "(JJIIF)V", (void*)nAddReplacementRun},
+        {"nBuildMeasuredText", "(JJ[CZZZ)J", (void*)nBuildMeasuredText},
+        {"nFreeBuilder", "(J)V", (void*)nFreeBuilder},
 };
 
 static const JNINativeMethod gMTMethods[] = {
diff --git a/libs/hwui/pipeline/skia/LayerDrawable.cpp b/libs/hwui/pipeline/skia/LayerDrawable.cpp
index 1439656..553b08f 100644
--- a/libs/hwui/pipeline/skia/LayerDrawable.cpp
+++ b/libs/hwui/pipeline/skia/LayerDrawable.cpp
@@ -15,12 +15,19 @@
  */
 
 #include "LayerDrawable.h"
+
+#include <shaders/shaders.h>
+#include <utils/Color.h>
 #include <utils/MathUtils.h>
 
+#include "DeviceInfo.h"
 #include "GrBackendSurface.h"
 #include "SkColorFilter.h"
+#include "SkRuntimeEffect.h"
 #include "SkSurface.h"
 #include "gl/GrGLTypes.h"
+#include "math/mat4.h"
+#include "system/graphics-base-v1.0.h"
 #include "system/window.h"
 
 namespace android {
@@ -69,6 +76,35 @@
              isIntegerAligned(dstDevRect.y()));
 }
 
+static sk_sp<SkShader> createLinearEffectShader(sk_sp<SkShader> shader,
+                                                const shaders::LinearEffect& linearEffect,
+                                                float maxDisplayLuminance, float maxLuminance) {
+    auto shaderString = SkString(shaders::buildLinearEffectSkSL(linearEffect));
+    auto [runtimeEffect, error] = SkRuntimeEffect::MakeForShader(std::move(shaderString));
+    if (!runtimeEffect) {
+        LOG_ALWAYS_FATAL("LinearColorFilter construction error: %s", error.c_str());
+    }
+
+    SkRuntimeShaderBuilder effectBuilder(std::move(runtimeEffect));
+
+    effectBuilder.child("child") = std::move(shader);
+
+    const auto uniforms = shaders::buildLinearEffectUniforms(linearEffect, mat4(),
+                                                             maxDisplayLuminance, maxLuminance);
+
+    for (const auto& uniform : uniforms) {
+        effectBuilder.uniform(uniform.name.c_str()).set(uniform.value.data(), uniform.value.size());
+    }
+
+    return effectBuilder.makeShader(nullptr, false);
+}
+
+static bool isHdrDataspace(ui::Dataspace dataspace) {
+    const auto transfer = dataspace & HAL_DATASPACE_TRANSFER_MASK;
+
+    return transfer == HAL_DATASPACE_TRANSFER_ST2084 || transfer == HAL_DATASPACE_TRANSFER_HLG;
+}
+
 // TODO: Context arg probably doesn't belong here – do debug check at callsite instead.
 bool LayerDrawable::DrawLayer(GrRecordingContext* context,
                               SkCanvas* canvas,
@@ -150,8 +186,30 @@
             sampling = SkSamplingOptions(SkFilterMode::kLinear);
         }
 
-        canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, sampling, &paint,
-                              constraint);
+        const auto sourceDataspace = static_cast<ui::Dataspace>(
+                ColorSpaceToADataSpace(layerImage->colorSpace(), layerImage->colorType()));
+        const SkImageInfo& imageInfo = canvas->imageInfo();
+        const auto destinationDataspace = static_cast<ui::Dataspace>(
+                ColorSpaceToADataSpace(imageInfo.colorSpace(), imageInfo.colorType()));
+
+        if (isHdrDataspace(sourceDataspace) || isHdrDataspace(destinationDataspace)) {
+            const auto effect = shaders::LinearEffect{
+                    .inputDataspace = sourceDataspace,
+                    .outputDataspace = destinationDataspace,
+                    .undoPremultipliedAlpha = layerImage->alphaType() == kPremul_SkAlphaType,
+                    .fakeInputDataspace = destinationDataspace};
+            auto shader = layerImage->makeShader(sampling,
+                                                 SkMatrix::RectToRect(skiaSrcRect, skiaDestRect));
+            constexpr float kMaxDisplayBrightess = 1000.f;
+            shader = createLinearEffectShader(std::move(shader), effect, kMaxDisplayBrightess,
+                                              layer->getMaxLuminanceNits());
+            paint.setShader(shader);
+            canvas->drawRect(skiaDestRect, paint);
+        } else {
+            canvas->drawImageRect(layerImage.get(), skiaSrcRect, skiaDestRect, sampling, &paint,
+                                  constraint);
+        }
+
         canvas->restore();
         // restore the original matrix
         if (useLayerTransform) {
diff --git a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
index 8abf4534..e6ef95b 100644
--- a/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
+++ b/libs/hwui/pipeline/skia/VkFunctorDrawable.cpp
@@ -72,6 +72,7 @@
             .clip_top = mClip.fTop,
             .clip_right = mClip.fRight,
             .clip_bottom = mClip.fBottom,
+            .is_layer = !vulkan_info.fFromSwapchainOrAndroidWindow,
     };
     mat4.getColMajor(&params.transform[0]);
     params.secondary_command_buffer = vulkan_info.fSecondaryCommandBuffer;
diff --git a/libs/hwui/private/hwui/DrawVkInfo.h b/libs/hwui/private/hwui/DrawVkInfo.h
index 4ae0f5a..5c59657 100644
--- a/libs/hwui/private/hwui/DrawVkInfo.h
+++ b/libs/hwui/private/hwui/DrawVkInfo.h
@@ -68,6 +68,9 @@
   int clip_top;
   int clip_right;
   int clip_bottom;
+
+  // Input: Whether destination surface is offscreen surface.
+  bool is_layer;
 };
 
 }  // namespace uirenderer
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index fe9a30a..611a4d9 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -426,7 +426,7 @@
     if (bufferInfo->skSurface.get() == nullptr) {
         bufferInfo->skSurface = SkSurface::MakeFromAHardwareBuffer(
                 mGrContext, ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()),
-                kTopLeft_GrSurfaceOrigin, mWindowInfo.colorspace, nullptr);
+                kTopLeft_GrSurfaceOrigin, mWindowInfo.colorspace, nullptr, /*from_window=*/true);
         if (bufferInfo->skSurface.get() == nullptr) {
             ALOGE("SkSurface::MakeFromAHardwareBuffer failed");
             mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer,
diff --git a/libs/input/PointerController.cpp b/libs/input/PointerController.cpp
index 8f04cfb..f43586f 100644
--- a/libs/input/PointerController.cpp
+++ b/libs/input/PointerController.cpp
@@ -17,24 +17,29 @@
 #define LOG_TAG "PointerController"
 //#define LOG_NDEBUG 0
 
-// Log debug messages about pointer updates
-#define DEBUG_POINTER_UPDATES 0
-
 #include "PointerController.h"
-#include "MouseCursorController.h"
 #include "PointerControllerContext.h"
-#include "TouchSpotController.h"
 
-#include <log/log.h>
-
-#include <SkBitmap.h>
 #include <SkBlendMode.h>
 #include <SkCanvas.h>
 #include <SkColor.h>
-#include <SkPaint.h>
 
 namespace android {
 
+namespace {
+
+const ui::Transform kIdentityTransform;
+
+} // namespace
+
+// --- PointerController::DisplayInfoListener ---
+
+void PointerController::DisplayInfoListener::onWindowInfosChanged(
+        const std::vector<android::gui::WindowInfo>&,
+        const std::vector<android::gui::DisplayInfo>& displayInfo) {
+    mPointerController.onDisplayInfosChanged(displayInfo);
+}
+
 // --- PointerController ---
 
 std::shared_ptr<PointerController> PointerController::create(
@@ -63,9 +68,16 @@
 PointerController::PointerController(const sp<PointerControllerPolicyInterface>& policy,
                                      const sp<Looper>& looper,
                                      const sp<SpriteController>& spriteController)
-      : mContext(policy, looper, spriteController, *this), mCursorController(mContext) {
+      : mContext(policy, looper, spriteController, *this),
+        mCursorController(mContext),
+        mDisplayInfoListener(new DisplayInfoListener(*this)) {
     std::scoped_lock lock(mLock);
     mLocked.presentation = Presentation::SPOT;
+    SurfaceComposerClient::getDefault()->addWindowInfosListener(mDisplayInfoListener);
+}
+
+PointerController::~PointerController() {
+    SurfaceComposerClient::getDefault()->removeWindowInfosListener(mDisplayInfoListener);
 }
 
 bool PointerController::getBounds(float* outMinX, float* outMinY, float* outMaxX,
@@ -74,7 +86,14 @@
 }
 
 void PointerController::move(float deltaX, float deltaY) {
-    mCursorController.move(deltaX, deltaY);
+    const int32_t displayId = mCursorController.getDisplayId();
+    vec2 transformed;
+    {
+        std::scoped_lock lock(mLock);
+        const auto& transform = getTransformForDisplayLocked(displayId);
+        transformed = transformWithoutTranslation(transform, {deltaX, deltaY});
+    }
+    mCursorController.move(transformed.x, transformed.y);
 }
 
 void PointerController::setButtonState(int32_t buttonState) {
@@ -86,12 +105,26 @@
 }
 
 void PointerController::setPosition(float x, float y) {
-    std::scoped_lock lock(mLock);
-    mCursorController.setPosition(x, y);
+    const int32_t displayId = mCursorController.getDisplayId();
+    vec2 transformed;
+    {
+        std::scoped_lock lock(mLock);
+        const auto& transform = getTransformForDisplayLocked(displayId);
+        transformed = transform.transform(x, y);
+    }
+    mCursorController.setPosition(transformed.x, transformed.y);
 }
 
 void PointerController::getPosition(float* outX, float* outY) const {
+    const int32_t displayId = mCursorController.getDisplayId();
     mCursorController.getPosition(outX, outY);
+    {
+        std::scoped_lock lock(mLock);
+        const auto& transform = getTransformForDisplayLocked(displayId);
+        const auto xy = transform.inverse().transform(*outX, *outY);
+        *outX = xy.x;
+        *outY = xy.y;
+    }
 }
 
 int32_t PointerController::getDisplayId() const {
@@ -130,11 +163,25 @@
 void PointerController::setSpots(const PointerCoords* spotCoords, const uint32_t* spotIdToIndex,
                                  BitSet32 spotIdBits, int32_t displayId) {
     std::scoped_lock lock(mLock);
+    std::array<PointerCoords, MAX_POINTERS> outSpotCoords{};
+    const ui::Transform& transform = getTransformForDisplayLocked(displayId);
+
+    for (BitSet32 idBits(spotIdBits); !idBits.isEmpty();) {
+        const uint32_t index = spotIdToIndex[idBits.clearFirstMarkedBit()];
+
+        const vec2 xy = transform.transform(spotCoords[index].getXYValue());
+        outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_X, xy.x);
+        outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_Y, xy.y);
+
+        float pressure = spotCoords[index].getAxisValue(AMOTION_EVENT_AXIS_PRESSURE);
+        outSpotCoords[index].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
+    }
+
     auto it = mLocked.spotControllers.find(displayId);
     if (it == mLocked.spotControllers.end()) {
         mLocked.spotControllers.try_emplace(displayId, displayId, mContext);
     }
-    mLocked.spotControllers.at(displayId).setSpots(spotCoords, spotIdToIndex, spotIdBits);
+    mLocked.spotControllers.at(displayId).setSpots(outSpotCoords.data(), spotIdToIndex, spotIdBits);
 }
 
 void PointerController::clearSpots() {
@@ -194,7 +241,7 @@
 
 void PointerController::onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports) {
     std::unordered_set<int32_t> displayIdSet;
-    for (DisplayViewport viewport : viewports) {
+    for (const DisplayViewport& viewport : viewports) {
         displayIdSet.insert(viewport.displayId);
     }
 
@@ -214,4 +261,17 @@
     }
 }
 
+void PointerController::onDisplayInfosChanged(const std::vector<gui::DisplayInfo>& displayInfo) {
+    std::scoped_lock lock(mLock);
+    mLocked.mDisplayInfos = displayInfo;
+}
+
+const ui::Transform& PointerController::getTransformForDisplayLocked(int displayId) const {
+    const auto& di = mLocked.mDisplayInfos;
+    auto it = std::find_if(di.begin(), di.end(), [displayId](const gui::DisplayInfo& info) {
+        return info.displayId == displayId;
+    });
+    return it != di.end() ? it->transform : kIdentityTransform;
+}
+
 } // namespace android
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 97567ba..796077f 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -47,7 +47,7 @@
             const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
             const sp<SpriteController>& spriteController);
 
-    virtual ~PointerController() = default;
+    ~PointerController() override;
 
     virtual bool getBounds(float* outMinX, float* outMinY, float* outMaxX, float* outMaxY) const;
     virtual void move(float deltaX, float deltaY);
@@ -72,6 +72,8 @@
     void reloadPointerResources();
     void onDisplayViewportsUpdated(std::vector<DisplayViewport>& viewports);
 
+    void onDisplayInfosChanged(const std::vector<gui::DisplayInfo>& displayInfos);
+
 private:
     friend PointerControllerContext::LooperCallback;
     friend PointerControllerContext::MessageHandler;
@@ -85,9 +87,23 @@
     struct Locked {
         Presentation presentation;
 
+        std::vector<gui::DisplayInfo> mDisplayInfos;
         std::unordered_map<int32_t /* displayId */, TouchSpotController> spotControllers;
     } mLocked GUARDED_BY(mLock);
 
+    class DisplayInfoListener : public gui::WindowInfosListener {
+    public:
+        explicit DisplayInfoListener(PointerController& pc) : mPointerController(pc){};
+        void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>&,
+                                  const std::vector<android::gui::DisplayInfo>&) override;
+
+    private:
+        PointerController& mPointerController;
+    };
+    sp<DisplayInfoListener> mDisplayInfoListener;
+
+    const ui::Transform& getTransformForDisplayLocked(int displayId) const REQUIRES(mLock);
+
     PointerController(const sp<PointerControllerPolicyInterface>& policy, const sp<Looper>& looper,
                       const sp<SpriteController>& spriteController);
     void clearSpotsLocked();
diff --git a/libs/input/SpriteController.cpp b/libs/input/SpriteController.cpp
index da21438..2b809ea 100644
--- a/libs/input/SpriteController.cpp
+++ b/libs/input/SpriteController.cpp
@@ -70,8 +70,8 @@
 }
 
 void SpriteController::invalidateSpriteLocked(const sp<SpriteImpl>& sprite) {
-    bool wasEmpty = mLocked.invalidatedSprites.isEmpty();
-    mLocked.invalidatedSprites.push(sprite);
+    bool wasEmpty = mLocked.invalidatedSprites.empty();
+    mLocked.invalidatedSprites.push_back(sprite);
     if (wasEmpty) {
         if (mLocked.transactionNestingCount != 0) {
             mLocked.deferredSpriteUpdate = true;
@@ -82,8 +82,8 @@
 }
 
 void SpriteController::disposeSurfaceLocked(const sp<SurfaceControl>& surfaceControl) {
-    bool wasEmpty = mLocked.disposedSurfaces.isEmpty();
-    mLocked.disposedSurfaces.push(surfaceControl);
+    bool wasEmpty = mLocked.disposedSurfaces.empty();
+    mLocked.disposedSurfaces.push_back(surfaceControl);
     if (wasEmpty) {
         mLooper->sendMessage(mHandler, Message(MSG_DISPOSE_SURFACES));
     }
@@ -113,7 +113,7 @@
 
         numSprites = mLocked.invalidatedSprites.size();
         for (size_t i = 0; i < numSprites; i++) {
-            const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites.itemAt(i);
+            const sp<SpriteImpl>& sprite = mLocked.invalidatedSprites[i];
 
             updates.push(SpriteUpdate(sprite, sprite->getStateLocked()));
             sprite->resetDirtyLocked();
@@ -305,7 +305,7 @@
 
 void SpriteController::doDisposeSurfaces() {
     // Collect disposed surfaces.
-    Vector<sp<SurfaceControl> > disposedSurfaces;
+    std::vector<sp<SurfaceControl>> disposedSurfaces;
     { // acquire lock
         AutoMutex _l(mLock);
 
@@ -313,6 +313,13 @@
         mLocked.disposedSurfaces.clear();
     } // release lock
 
+    // Remove the parent from all surfaces.
+    SurfaceComposerClient::Transaction t;
+    for (const sp<SurfaceControl>& sc : disposedSurfaces) {
+        t.reparent(sc, nullptr);
+    }
+    t.apply();
+
     // Release the last reference to each surface outside of the lock.
     // We don't want the surfaces to be deleted while we are holding our lock.
     disposedSurfaces.clear();
diff --git a/libs/input/SpriteController.h b/libs/input/SpriteController.h
index 2a80d95..2e9cb96 100644
--- a/libs/input/SpriteController.h
+++ b/libs/input/SpriteController.h
@@ -251,8 +251,8 @@
     sp<SurfaceComposerClient> mSurfaceComposerClient;
 
     struct Locked {
-        Vector<sp<SpriteImpl> > invalidatedSprites;
-        Vector<sp<SurfaceControl> > disposedSurfaces;
+        std::vector<sp<SpriteImpl>> invalidatedSprites;
+        std::vector<sp<SurfaceControl>> disposedSurfaces;
         uint32_t transactionNestingCount;
         bool deferredSpriteUpdate;
     } mLocked; // guarded by mLock
diff --git a/lint-baseline.xml b/lint-baseline.xml
new file mode 100644
index 0000000..79b2155
--- /dev/null
+++ b/lint-baseline.xml
@@ -0,0 +1,565 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<issues format="6" by="lint 7.1.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="7.1.0-dev">
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="        final String component = Settings.Secure.getString(getContentResolver(),"
+        errorLine2="                                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/accessibility/dialog/AccessibilityButtonChooserActivity.java"
+            line="60"
+            column="42"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        return Settings.Secure.getInt(context.getContentResolver(),"
+        errorLine2="                               ~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java"
+            line="188"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        return Settings.Secure.getInt(context.getContentResolver(),"
+        errorLine2="                               ~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/accessibility/util/AccessibilityStatsLogUtils.java"
+            line="194"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        return Settings.Secure.getInt(context.getContentResolver(),"
+        errorLine2="                       ~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/app/AssistUtils.java"
+            line="216"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.System#getInt()` called from system process. Please call `android.provider.Settings.System#getIntForUser()` instead. "
+        errorLine1="     * volume, false otherwise."
+        errorLine2="                     ~~~~~~">
+        <location
+            file="frameworks/base/media/java/android/media/AudioManager.java"
+            line="1028"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="    public final boolean isEnabled() {"
+        errorLine2="                                     ^">
+        <location
+            file="frameworks/base/core/java/android/view/accessibility/CaptioningManager.java"
+            line="70"
+            column="38"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="    public final String getRawLocale() {"
+        errorLine2="                                       ^">
+        <location
+            file="frameworks/base/core/java/android/view/accessibility/CaptioningManager.java"
+            line="81"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getFloat()` called from system process. Please call `android.provider.Settings.Secure#getFloatForUser()` instead. "
+        errorLine1="    public final float getFontScale() {"
+        errorLine2="                                      ^">
+        <location
+            file="frameworks/base/core/java/android/view/accessibility/CaptioningManager.java"
+            line="111"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="    public int getRawUserStyle() {"
+        errorLine2="                                 ^">
+        <location
+            file="frameworks/base/core/java/android/view/accessibility/CaptioningManager.java"
+            line="120"
+            column="34"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            final int foregroundColor = Secure.getInt("
+        errorLine2="                       ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/view/accessibility/CaptioningManager.java"
+            line="478"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            final int backgroundColor = Secure.getInt("
+        errorLine2="                       ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/view/accessibility/CaptioningManager.java"
+            line="480"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            final int edgeType = Secure.getInt("
+        errorLine2="                ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/view/accessibility/CaptioningManager.java"
+            line="482"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            final int edgeColor = Secure.getInt("
+        errorLine2="                 ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/view/accessibility/CaptioningManager.java"
+            line="484"
+            column="18"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            final int windowColor = Secure.getInt("
+        errorLine2="                   ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/view/accessibility/CaptioningManager.java"
+            line="486"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="            String rawTypeface = Secure.getString(cr, Secure.ACCESSIBILITY_CAPTIONING_TYPEFACE);"
+        errorLine2="                ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/view/accessibility/CaptioningManager.java"
+            line="489"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="        String nearbyComponent = Settings.Secure.getString("
+        errorLine2="                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/app/ChooserActivity.java"
+            line="1156"
+            column="26"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        final ContentResolver cr = context.getContentResolver();"
+        errorLine2="                                       ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/hardware/display/ColorDisplayManager.java"
+            line="587"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        return Secure.getInt(cr, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0) == 1"
+        errorLine2="                                                                   ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/hardware/display/ColorDisplayManager.java"
+            line="588"
+            column="68"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        int inversionEnabled = Settings.Secure.getInt(contentResolver,"
+        errorLine2="                                       ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/security/ConfirmationPrompt.java"
+            line="220"
+            column="40"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.System#getFloat()` called from system process. Please call `android.provider.Settings.System#getFloatForUser()` instead. "
+        errorLine1="        float fontScale = Settings.System.getFloat(contentResolver,"
+        errorLine2="                                  ~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/security/ConfirmationPrompt.java"
+            line="225"
+            column="35"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            int a11yEnabled = Settings.Secure.getInt(contentResolver,"
+        errorLine2="                                      ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/security/ConfirmationPrompt.java"
+            line="237"
+            column="39"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="                Secure.getInt(resolver, Secure.RELEASE_COMPRESS_BLOCKS_ON_INSTALL, 1) != 0;"
+        errorLine2="               ~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/content/F2fsUtils.java"
+            line="96"
+            column="16"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.System#getInt()` called from system process. Please call `android.provider.Settings.System#getIntForUser()` instead. "
+        errorLine1="        int speed = DEFAULT_POINTER_SPEED;"
+        errorLine2="                     ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/hardware/input/InputManager.java"
+            line="865"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="        final ContentResolver contentResolver = fallbackContext.getContentResolver();"
+        errorLine2="                                                           ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/view/inputmethod/InputMethodManager.java"
+            line="2860"
+            column="60"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            if (mShowImeWithHardKeyboard == ShowImeWithHardKeyboardType.UNKNOWN) {"
+        errorLine2="                                                                              ^">
+        <location
+            file="frameworks/base/core/java/android/inputmethodservice/InputMethodService.java"
+            line="1205"
+            column="79"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            if (showImeWithHardKeyboardUri.equals(uri)) {"
+        errorLine2="                                                     ^">
+        <location
+            file="frameworks/base/core/java/android/inputmethodservice/InputMethodService.java"
+            line="1225"
+            column="54"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="                        RemoteViews.MARGIN_BOTTOM, 0);"
+        errorLine2="                            ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/app/Notification.java"
+            line="5619"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="            return Settings.Secure.getInt(context.getContentResolver(),"
+        errorLine2="                   ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/hardware/biometrics/ParentalControlsUtilsInternal.java"
+            line="40"
+            column="20"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        return Settings.Secure.getInt(mContext.getContentResolver(),"
+        errorLine2="                               ~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/policy/PhoneFallbackEventHandler.java"
+            line="328"
+            column="32"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        boolean isTvSetupComplete = Settings.Secure.getInt(getContext().getContentResolver(),"
+        errorLine2="                            ~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java"
+            line="3129"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        isTvSetupComplete &amp;= Settings.Secure.getInt(getContext().getContentResolver(),"
+        errorLine2="                     ~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java"
+            line="3131"
+            column="22"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.System#getString()` called from system process. Please call `android.provider.Settings.System#getStringForUser()` instead. "
+        errorLine1="            final String touchDataJson = Settings.System.getString("
+        errorLine2="                                                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/app/PlatLogoActivity.java"
+            line="184"
+            column="58"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        return Settings.Secure.getInt(mContext.getContentResolver(), name, 0) == 1;"
+        errorLine2="       ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/service/quickaccesswallet/QuickAccessWalletClientImpl.java"
+            line="463"
+            column="8"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="        String comp = Settings.Secure.getString(cr, Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);"
+        errorLine2="                      ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/service/quickaccesswallet/QuickAccessWalletServiceInfo.java"
+            line="97"
+            column="23"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.System#getInt()` called from system process. Please call `android.provider.Settings.System#getIntForUser()` instead. "
+        errorLine1="            final String setting = getDefaultRingtoneSetting(type);"
+        errorLine2="                                            ~~~~~~">
+        <location
+            file="frameworks/base/media/java/android/media/RingtoneManager.java"
+            line="1105"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="        final String targetString = Settings.Secure.getString(context.getContentResolver(),"
+        errorLine2="                                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/accessibility/util/ShortcutUtils.java"
+            line="55"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="        final String targetsValue = Settings.Secure.getString(context.getContentResolver(),"
+        errorLine2="                                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/accessibility/util/ShortcutUtils.java"
+            line="82"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="        final String targetString = Settings.Secure.getString(context.getContentResolver(),"
+        errorLine2="                                            ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/accessibility/util/ShortcutUtils.java"
+            line="112"
+            column="45"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="        String serviceComponent = Settings.Secure.getString(mContext.getContentResolver(),"
+        errorLine2="  ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/speech/SpeechRecognizer.java"
+            line="665"
+            column="3"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.System#getInt()` called from system process. Please call `android.provider.Settings.System#getIntForUser()` instead. "
+        errorLine1="        boolean cap = System.getInt(resolver, System.TEXT_AUTO_CAPS, 1) > 0;"
+        errorLine2="                             ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/text/method/TextKeyListener.java"
+            line="296"
+            column="30"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.System#getInt()` called from system process. Please call `android.provider.Settings.System#getIntForUser()` instead. "
+        errorLine1="        boolean text = System.getInt(resolver, System.TEXT_AUTO_REPLACE, 1) > 0;"
+        errorLine2="                              ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/text/method/TextKeyListener.java"
+            line="297"
+            column="31"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.System#getInt()` called from system process. Please call `android.provider.Settings.System#getIntForUser()` instead. "
+        errorLine1="        boolean period = System.getInt(resolver, System.TEXT_AUTO_PUNCTUATE, 1) > 0;"
+        errorLine2="                                ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/text/method/TextKeyListener.java"
+            line="298"
+            column="33"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.System#getInt()` called from system process. Please call `android.provider.Settings.System#getIntForUser()` instead. "
+        errorLine1="        boolean pw = System.getInt(resolver, System.TEXT_SHOW_PASSWORD, 1) > 0;"
+        errorLine2="                            ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/text/method/TextKeyListener.java"
+            line="299"
+            column="29"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        return Settings.Secure.getInt(getContentResolver(), name, defaultValue);"
+        errorLine2="                       ~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/speech/tts/TextToSpeechService.java"
+            line="422"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        return Settings.Secure.getInt(getContext().getContentResolver(),"
+        errorLine2="                       ~~~~~~">
+        <location
+            file="frameworks/base/core/java/com/android/internal/accessibility/dialog/ToggleAllowListingFeatureTarget.java"
+            line="63"
+            column="24"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="        String engine = getString(mContext.getContentResolver(),"
+        errorLine2="                ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/speech/tts/TtsEngines.java"
+            line="116"
+            column="17"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="                getString(mContext.getContentResolver(), Settings.Secure.TTS_DEFAULT_LOCALE));"
+        errorLine2="        ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/speech/tts/TtsEngines.java"
+            line="337"
+            column="9"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="                    getString(mContext.getContentResolver(), Settings.Secure.TTS_DEFAULT_LOCALE),"
+        errorLine2="            ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/speech/tts/TtsEngines.java"
+            line="373"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="        final String prefList = Settings.Secure.getString(mContext.getContentResolver(),"
+        errorLine2="                                        ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/speech/tts/TtsEngines.java"
+            line="527"
+            column="41"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getInt()` called from system process. Please call `android.provider.Settings.Secure#getIntForUser()` instead. "
+        errorLine1="        }"
+        errorLine2="         ^">
+        <location
+            file="frameworks/base/core/java/android/service/autofill/UserData.java"
+            line="535"
+            column="10"/>
+    </issue>
+
+    <issue
+        id="NonUserGetterCalled"
+        message="`android.provider.Settings.Secure#getString()` called from system process. Please call `android.provider.Settings.Secure#getStringForUser()` instead. "
+        errorLine1="    public static boolean isActiveService(Context context, ComponentName service) {"
+        errorLine2="                                                                         ~~~~~~~~~">
+        <location
+            file="frameworks/base/core/java/android/service/voice/VoiceInteractionService.java"
+            line="156"
+            column="74"/>
+    </issue>
+
+</issues>
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 5d5c0fc..8054fd4 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -125,6 +125,9 @@
     boolean isAdasGnssLocationEnabledForUser(int userId);
     void setAdasGnssLocationEnabledForUser(boolean enabled, int userId);
 
+    boolean isAutoGnssSuspended();
+    void setAutoGnssSuspended(boolean suspended);
+
     void addTestProvider(String name, in ProviderProperties properties,
         in List<String> locationTags, String packageName, @nullable String attributionTag);
     void removeTestProvider(String provider, String packageName, @nullable String attributionTag);
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index becaca9..61caa0b 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -758,6 +758,51 @@
     }
 
     /**
+     * Set whether GNSS requests are suspended on the device.
+     *
+     * This method was added to help support power management use cases on automotive devices. More
+     * specifically, it is being added to fix a suspend to RAM issue where the SoC can't go into
+     * a lower power state when applications are actively requesting GNSS updates.
+     *
+     * Ideally, the issue should be fixed at a lower layer in the stack, but this API introduces a
+     * workaround in the platform layer. This API allows car specific services to halt GNSS requests
+     * based on changes to the car power policy, which will in turn enable the device to go into
+     * suspend.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.AUTOMOTIVE_GNSS_CONTROLS)
+    public void setAutoGnssSuspended(boolean suspended) {
+        try {
+            mService.setAutoGnssSuspended(suspended);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Return whether GNSS requests are suspended or not.
+     *
+     * This method was added to help support power management use cases on automotive devices. More
+     * specifically, it is being added as part of the fix for a suspend to RAM issue where the SoC
+     * can't go into a lower power state when applications are actively requesting GNSS updates.
+     *
+     * @return true if GNSS requests are suspended and false if they aren't.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.AUTOMOTIVE_GNSS_CONTROLS)
+    public boolean isAutoGnssSuspended() {
+        try {
+            return mService.isAutoGnssSuspended();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Gets the last known location from the fused provider, or null if there is no last known
      * location. The returned location may be quite old in some circumstances, so the age of the
      * location should always be checked.
diff --git a/media/Android.bp b/media/Android.bp
index 15b24b2..fcdfd72 100644
--- a/media/Android.bp
+++ b/media/Android.bp
@@ -115,6 +115,7 @@
 aidl_interface {
     name: "android.media.soundtrigger.types",
     vendor_available: true,
+    host_supported: true,
     flags: [
         "-Werror",
         "-Weverything",
diff --git a/media/aidl/android/media/audio/common/AudioMode.aidl b/media/aidl/android/media/audio/common/AudioMode.aidl
index cc03813..701bcb6 100644
--- a/media/aidl/android/media/audio/common/AudioMode.aidl
+++ b/media/aidl/android/media/audio/common/AudioMode.aidl
@@ -45,4 +45,8 @@
     IN_COMMUNICATION = 3,
     /** Call screening in progress. */
     CALL_SCREEN = 4,
+    /** PSTN Call redirection  in progress. */
+    SYS_RESERVED_CALL_REDIRECT = 5,
+    /** VoIP Call redirection  in progress. */
+    SYS_RESERVED_COMMUNICATION_REDIRECT = 6,
 }
diff --git a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioMode.aidl b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioMode.aidl
index 8ae1c10..8256c1c 100644
--- a/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioMode.aidl
+++ b/media/aidl_api/android.media.audio.common.types/current/android/media/audio/common/AudioMode.aidl
@@ -42,4 +42,6 @@
   IN_CALL = 2,
   IN_COMMUNICATION = 3,
   CALL_SCREEN = 4,
+  SYS_RESERVED_CALL_REDIRECT = 5,
+  SYS_RESERVED_COMMUNICATION_REDIRECT = 6,
 }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index e3ed703..337b45c 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -30,13 +30,17 @@
 import android.annotation.TestApi;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.compat.CompatChanges;
 import android.bluetooth.BluetoothCodecConfig;
 import android.bluetooth.BluetoothDevice;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledSince;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.media.AudioAttributes.AttributeSystemUsage;
+import android.media.CallbackUtil.ListenerInfo;
 import android.media.audiopolicy.AudioPolicy;
 import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener;
 import android.media.audiopolicy.AudioProductStrategy;
@@ -58,6 +62,7 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -1017,6 +1022,29 @@
     }
 
     /**
+     * Returns the current user setting for ramping ringer on incoming phone call ringtone.
+     *
+     * @return true if the incoming phone call ringtone is configured to gradually increase its
+     * volume, false otherwise.
+     */
+    public boolean isRampingRingerEnabled() {
+        return Settings.System.getInt(getContext().getContentResolver(),
+                Settings.System.APPLY_RAMPING_RINGER, 0) != 0;
+    }
+
+    /**
+     * Sets the flag for enabling ramping ringer on incoming phone call ringtone.
+     *
+     * @see #isRampingRingerEnabled()
+     * @hide
+     */
+    @TestApi
+    public void setRampingRingerEnabled(boolean enabled) {
+        Settings.System.putInt(getContext().getContentResolver(),
+                Settings.System.APPLY_RAMPING_RINGER, enabled ? 1 : 0);
+    }
+
+    /**
      * Checks valid ringer mode values.
      *
      * @return true if the ringer mode indicated is valid, false otherwise.
@@ -2840,6 +2868,14 @@
     }
 
     /**
+     * This change id controls use of audio modes for call audio redirection.
+     * @hide
+     */
+    @ChangeId
+    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+    public static final long CALL_REDIRECTION_AUDIO_MODES = 189472651L; // buganizer id
+
+    /**
      * Returns the current audio mode.
      *
      * @return      the current audio mode.
@@ -2858,6 +2894,12 @@
             }
             if (mode == MODE_CALL_SCREENING && sdk <= Build.VERSION_CODES.Q) {
                 mode = MODE_IN_CALL;
+            } else if (mode == MODE_CALL_REDIRECT
+                    && !CompatChanges.isChangeEnabled(CALL_REDIRECTION_AUDIO_MODES)) {
+                mode = MODE_IN_CALL;
+            } else if (mode == MODE_COMMUNICATION_REDIRECT
+                    && !CompatChanges.isChangeEnabled(CALL_REDIRECTION_AUDIO_MODES)) {
+                mode = MODE_IN_COMMUNICATION;
             }
             return mode;
         } catch (RemoteException e) {
@@ -2883,79 +2925,33 @@
      * List is lazy-initialized on first registration
      */
     @GuardedBy("mModeListenerLock")
-    private @Nullable ArrayList<ModeListenerInfo> mModeListeners;
+    private @Nullable ArrayList<ListenerInfo<OnModeChangedListener>> mModeListeners;
 
     @GuardedBy("mModeListenerLock")
     private ModeDispatcherStub mModeDispatcherStub;
 
-    private final class ModeDispatcherStub
-            extends IAudioModeDispatcher.Stub {
+    private final class ModeDispatcherStub extends IAudioModeDispatcher.Stub {
+
+        public void register(boolean register) {
+            try {
+                if (register) {
+                    getService().registerModeDispatcher(this);
+                } else {
+                    getService().unregisterModeDispatcher(this);
+                }
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        }
 
         @Override
+        @SuppressLint("GuardedBy") // lock applied inside callListeners method
         public void dispatchAudioModeChanged(int mode) {
-            // make a shallow copy of listeners so callback is not executed under lock
-            final ArrayList<ModeListenerInfo> modeListeners;
-            synchronized (mModeListenerLock) {
-                if (mModeListeners == null || mModeListeners.size() == 0) {
-                    return;
-                }
-                modeListeners = (ArrayList<ModeListenerInfo>) mModeListeners.clone();
-            }
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                for (ModeListenerInfo info : modeListeners) {
-                    info.mExecutor.execute(() ->
-                            info.mListener.onModeChanged(mode));
-                }
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
+            CallbackUtil.callListeners(mModeListeners, mModeListenerLock,
+                    (listener) -> listener.onModeChanged(mode));
         }
     }
 
-    private static class ModeListenerInfo {
-        final @NonNull OnModeChangedListener mListener;
-        final @NonNull Executor mExecutor;
-
-        ModeListenerInfo(OnModeChangedListener listener, Executor exe) {
-            mListener = listener;
-            mExecutor = exe;
-        }
-    }
-
-    @GuardedBy("mModeListenerLock")
-    private boolean hasModeListener(OnModeChangedListener listener) {
-        return getModeListenerInfo(listener) != null;
-    }
-
-    @GuardedBy("mModeListenerLock")
-    private @Nullable ModeListenerInfo getModeListenerInfo(
-            OnModeChangedListener listener) {
-        if (mModeListeners == null) {
-            return null;
-        }
-        for (ModeListenerInfo info : mModeListeners) {
-            if (info.mListener == listener) {
-                return info;
-            }
-        }
-        return null;
-    }
-
-
-    @GuardedBy("mModeListenerLock")
-    /**
-     * @return true if the listener was removed from the list
-     */
-    private boolean removeModeListener(OnModeChangedListener listener) {
-        final ModeListenerInfo infoToRemove = getModeListenerInfo(listener);
-        if (infoToRemove != null) {
-            mModeListeners.remove(infoToRemove);
-            return true;
-        }
-        return false;
-    }
-
     /**
      * Adds a listener to be notified of changes to the audio mode.
      * See {@link #getMode()}
@@ -2965,30 +2961,14 @@
     public void addOnModeChangedListener(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull OnModeChangedListener listener) {
-        Objects.requireNonNull(executor);
-        Objects.requireNonNull(listener);
         synchronized (mModeListenerLock) {
-            if (hasModeListener(listener)) {
-                throw new IllegalArgumentException("attempt to call addOnModeChangedListener() "
-                        + "on a previously registered listener");
-            }
-            // lazy initialization of the list of strategy-preferred device listener
-            if (mModeListeners == null) {
-                mModeListeners = new ArrayList<>();
-            }
-            final int oldCbCount = mModeListeners.size();
-            mModeListeners.add(new ModeListenerInfo(listener, executor));
-            if (oldCbCount == 0) {
-                // register binder for callbacks
-                if (mModeDispatcherStub == null) {
-                    mModeDispatcherStub = new ModeDispatcherStub();
-                }
-                try {
-                    getService().registerModeDispatcher(mModeDispatcherStub);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
+            final Pair<ArrayList<ListenerInfo<OnModeChangedListener>>, ModeDispatcherStub> res =
+                    CallbackUtil.addListener("addOnModeChangedListener",
+                            executor, listener, mModeListeners, mModeDispatcherStub,
+                            () -> new ModeDispatcherStub(),
+                            stub -> stub.register(true));
+            mModeListeners = res.first;
+            mModeDispatcherStub = res.second;
         }
     }
 
@@ -2998,23 +2978,13 @@
      * @param listener
      */
     public void removeOnModeChangedListener(@NonNull OnModeChangedListener listener) {
-        Objects.requireNonNull(listener);
         synchronized (mModeListenerLock) {
-            if (!removeModeListener(listener)) {
-                throw new IllegalArgumentException("attempt to call removeOnModeChangedListener() "
-                        + "on an unregistered listener");
-            }
-            if (mModeListeners.size() == 0) {
-                // unregister binder for callbacks
-                try {
-                    getService().unregisterModeDispatcher(mModeDispatcherStub);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                } finally {
-                    mModeDispatcherStub = null;
-                    mModeListeners = null;
-                }
-            }
+            final Pair<ArrayList<ListenerInfo<OnModeChangedListener>>, ModeDispatcherStub> res =
+                    CallbackUtil.removeListener("removeOnModeChangedListener",
+                            listener, mModeListeners, mModeDispatcherStub,
+                            stub -> stub.register(false));
+            mModeListeners = res.first;
+            mModeDispatcherStub = res.second;
         }
     }
 
@@ -3075,13 +3045,26 @@
      */
     public static final int MODE_CALL_SCREENING     = AudioSystem.MODE_CALL_SCREENING;
 
+    /**
+     * A telephony call is established and its audio is being redirected to another device.
+     */
+    public static final int MODE_CALL_REDIRECT   = AudioSystem.MODE_CALL_REDIRECT;
+
+    /**
+     * An audio/video chat or VoIP call is established and its audio is being redirected to another
+     * device.
+     */
+    public static final int MODE_COMMUNICATION_REDIRECT = AudioSystem.MODE_COMMUNICATION_REDIRECT;
+
     /** @hide */
     @IntDef(flag = false, prefix = "MODE_", value = {
             MODE_NORMAL,
             MODE_RINGTONE,
             MODE_IN_CALL,
             MODE_IN_COMMUNICATION,
-            MODE_CALL_SCREENING }
+            MODE_CALL_SCREENING,
+            MODE_CALL_REDIRECT,
+            MODE_COMMUNICATION_REDIRECT}
     )
     @Retention(RetentionPolicy.SOURCE)
     public @interface AudioMode {}
@@ -7616,31 +7599,15 @@
     public void addOnCommunicationDeviceChangedListener(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull OnCommunicationDeviceChangedListener listener) {
-        Objects.requireNonNull(executor);
-        Objects.requireNonNull(listener);
         synchronized (mCommDevListenerLock) {
-            if (hasCommDevListener(listener)) {
-                throw new IllegalArgumentException(
-                        "attempt to call addOnCommunicationDeviceChangedListener() "
-                                + "on a previously registered listener");
-            }
-            // lazy initialization of the list of strategy-preferred device listener
-            if (mCommDevListeners == null) {
-                mCommDevListeners = new ArrayList<>();
-            }
-            final int oldCbCount = mCommDevListeners.size();
-            mCommDevListeners.add(new CommDevListenerInfo(listener, executor));
-            if (oldCbCount == 0 && mCommDevListeners.size() > 0) {
-                // register binder for callbacks
-                if (mCommDevDispatcherStub == null) {
-                    mCommDevDispatcherStub = new CommunicationDeviceDispatcherStub();
-                }
-                try {
-                    getService().registerCommunicationDeviceDispatcher(mCommDevDispatcherStub);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
+            final Pair<ArrayList<ListenerInfo<OnCommunicationDeviceChangedListener>>,
+                    CommunicationDeviceDispatcherStub> res =
+                    CallbackUtil.addListener("addOnCommunicationDeviceChangedListener",
+                            executor, listener, mCommDevListeners, mCommDevDispatcherStub,
+                            () -> new CommunicationDeviceDispatcherStub(),
+                            stub -> stub.register(true));
+            mCommDevListeners = res.first;
+            mCommDevDispatcherStub = res.second;
         }
     }
 
@@ -7651,25 +7618,14 @@
      */
     public void removeOnCommunicationDeviceChangedListener(
             @NonNull OnCommunicationDeviceChangedListener listener) {
-        Objects.requireNonNull(listener);
         synchronized (mCommDevListenerLock) {
-            if (!removeCommDevListener(listener)) {
-                throw new IllegalArgumentException(
-                        "attempt to call removeOnCommunicationDeviceChangedListener() "
-                                + "on an unregistered listener");
-            }
-            if (mCommDevListeners.size() == 0) {
-                // unregister binder for callbacks
-                try {
-                    getService().unregisterCommunicationDeviceDispatcher(
-                            mCommDevDispatcherStub);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                } finally {
-                    mCommDevDispatcherStub = null;
-                    mCommDevListeners = null;
-                }
-            }
+            final Pair<ArrayList<ListenerInfo<OnCommunicationDeviceChangedListener>>,
+                    CommunicationDeviceDispatcherStub> res =
+                    CallbackUtil.removeListener("removeOnCommunicationDeviceChangedListener",
+                            listener, mCommDevListeners, mCommDevDispatcherStub,
+                            stub -> stub.register(false));
+            mCommDevListeners = res.first;
+            mCommDevDispatcherStub = res.second;
         }
     }
 
@@ -7679,17 +7635,8 @@
      * List is lazy-initialized on first registration
      */
     @GuardedBy("mCommDevListenerLock")
-    private @Nullable ArrayList<CommDevListenerInfo> mCommDevListeners;
-
-    private static class CommDevListenerInfo {
-        final @NonNull OnCommunicationDeviceChangedListener mListener;
-        final @NonNull Executor mExecutor;
-
-        CommDevListenerInfo(OnCommunicationDeviceChangedListener listener, Executor exe) {
-            mListener = listener;
-            mExecutor = exe;
-        }
-    }
+    private @Nullable
+            ArrayList<ListenerInfo<OnCommunicationDeviceChangedListener>> mCommDevListeners;
 
     @GuardedBy("mCommDevListenerLock")
     private CommunicationDeviceDispatcherStub mCommDevDispatcherStub;
@@ -7697,59 +7644,25 @@
     private final class CommunicationDeviceDispatcherStub
             extends ICommunicationDeviceDispatcher.Stub {
 
-        @Override
-        public void dispatchCommunicationDeviceChanged(int portId) {
-            // make a shallow copy of listeners so callback is not executed under lock
-            final ArrayList<CommDevListenerInfo> commDevListeners;
-            synchronized (mCommDevListenerLock) {
-                if (mCommDevListeners == null || mCommDevListeners.size() == 0) {
-                    return;
-                }
-                commDevListeners = (ArrayList<CommDevListenerInfo>) mCommDevListeners.clone();
-            }
-            AudioDeviceInfo device = getDeviceForPortId(portId, GET_DEVICES_OUTPUTS);
-            final long ident = Binder.clearCallingIdentity();
+        public void register(boolean register) {
             try {
-                for (CommDevListenerInfo info : commDevListeners) {
-                    info.mExecutor.execute(() ->
-                            info.mListener.onCommunicationDeviceChanged(device));
+                if (register) {
+                    getService().registerCommunicationDeviceDispatcher(this);
+                } else {
+                    getService().unregisterCommunicationDeviceDispatcher(this);
                 }
-            } finally {
-                Binder.restoreCallingIdentity(ident);
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
             }
         }
-    }
 
-    @GuardedBy("mCommDevListenerLock")
-    private @Nullable CommDevListenerInfo getCommDevListenerInfo(
-            OnCommunicationDeviceChangedListener listener) {
-        if (mCommDevListeners == null) {
-            return null;
+        @Override
+        @SuppressLint("GuardedBy") // lock applied inside callListeners method
+        public void dispatchCommunicationDeviceChanged(int portId) {
+            AudioDeviceInfo device = getDeviceForPortId(portId, GET_DEVICES_OUTPUTS);
+            CallbackUtil.callListeners(mCommDevListeners, mCommDevListenerLock,
+                    (listener) -> listener.onCommunicationDeviceChanged(device));
         }
-        for (CommDevListenerInfo info : mCommDevListeners) {
-            if (info.mListener == listener) {
-                return info;
-            }
-        }
-        return null;
-    }
-
-    @GuardedBy("mCommDevListenerLock")
-    private boolean hasCommDevListener(OnCommunicationDeviceChangedListener listener) {
-        return getCommDevListenerInfo(listener) != null;
-    }
-
-    @GuardedBy("mCommDevListenerLock")
-    /**
-     * @return true if the listener was removed from the list
-     */
-    private boolean removeCommDevListener(OnCommunicationDeviceChangedListener listener) {
-        final CommDevListenerInfo infoToRemove = getCommDevListenerInfo(listener);
-        if (infoToRemove != null) {
-            mCommDevListeners.remove(infoToRemove);
-            return true;
-        }
-        return false;
     }
 
     //---------------------------------------------------------
@@ -7808,4 +7721,4 @@
             return mHandler;
         }
     }
-}
+}
\ No newline at end of file
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 60c9e1c..16cb5f4 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -199,7 +199,11 @@
     /** @hide */
     public static final int MODE_CALL_SCREENING     = 4;
     /** @hide */
-    public static final int NUM_MODES               = 5;
+    public static final int MODE_CALL_REDIRECT     = 5;
+    /** @hide */
+    public static final int MODE_COMMUNICATION_REDIRECT  = 6;
+    /** @hide */
+    public static final int NUM_MODES               = 7;
 
     /** @hide */
     public static String modeToString(int mode) {
@@ -211,6 +215,8 @@
             case MODE_NORMAL: return "MODE_NORMAL";
             case MODE_RINGTONE: return "MODE_RINGTONE";
             case MODE_CALL_SCREENING: return "MODE_CALL_SCREENING";
+            case MODE_CALL_REDIRECT: return "MODE_CALL_REDIRECT";
+            case MODE_COMMUNICATION_REDIRECT: return "MODE_COMMUNICATION_REDIRECT";
             default: return "unknown mode (" + mode + ")";
         }
     }
diff --git a/media/java/android/media/CallbackUtil.java b/media/java/android/media/CallbackUtil.java
new file mode 100644
index 0000000..ac39317
--- /dev/null
+++ b/media/java/android/media/CallbackUtil.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2021 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 android.media;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.media.permission.ClearCallingIdentityContext;
+import android.media.permission.SafeCloseable;
+import android.util.Log;
+import android.util.Pair;
+
+import java.util.ArrayList;
+import java.util.Objects;
+import java.util.concurrent.Executor;
+
+/**
+ * @hide
+ * A utility class to implement callback listeners and their management.
+ * This is meant to be used for lazily-initialized listener lists and stubs for event reception,
+ * typically received from server (e.g. AudioService).
+ */
+
+/*package*/ class CallbackUtil {
+
+    private static final String TAG = "CallbackUtil";
+
+    /**
+     * Container class to store a listener and associated Executor
+     * @param <T> the type of the listener
+     */
+    static class ListenerInfo<T> {
+        final @NonNull T mListener;
+        final @NonNull Executor mExecutor;
+
+        ListenerInfo(@NonNull T listener, @NonNull Executor exe) {
+            mListener = listener;
+            mExecutor = exe;
+        }
+    }
+
+    /**
+     * Finds the listener information (listener + Executor) in a given list of listeners
+     * @param listener the listener to find
+     * @param listeners the list of listener informations, can be null if not instantiated yet
+     * @param <T> the type of the listeners
+     * @return null if the listener is not in the given list of listener informations
+     */
+    static <T> @Nullable ListenerInfo<T> getListenerInfo(
+            @NonNull T listener, @Nullable ArrayList<ListenerInfo<T>> listeners) {
+        if (listeners == null) {
+            return null;
+        }
+        for (ListenerInfo<T> info : listeners) {
+            if (info.mListener == listener) {
+                return info;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns true if the given listener is present in the list of listener informations
+     * @param listener the listener to find
+     * @param listeners the list of listener informations, can be null if not instantiated yet
+     * @param <T> the type of the listeners
+     * @return true if the listener is in the list
+     */
+    static <T> boolean hasListener(@NonNull T listener,
+            @Nullable ArrayList<ListenerInfo<T>> listeners) {
+        return getListenerInfo(listener, listeners) != null;
+    }
+
+    /**
+     * Removes the given listener from the list of listener informations
+     * @param listener the listener to remove
+     * @param listeners the list of listener informations, can be null if not instantiated yet
+     * @param <T> the type of the listeners
+     * @return true if the listener was found and removed from the list, false otherwise
+     */
+    static <T> boolean removeListener(@NonNull T listener,
+            @Nullable ArrayList<ListenerInfo<T>> listeners) {
+        final ListenerInfo<T> infoToRemove = getListenerInfo(listener, listeners);
+        if (infoToRemove != null) {
+            listeners.remove(infoToRemove);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Adds a listener and associated Executor in the list of listeners.
+     * This method handles the lazy initialization of both the list of listeners and the stub
+     * used to receive the events that will be forwarded to the listener, see the returned pair
+     * for the updated references.
+     * @param methodName the name of the method calling this, for inclusion in the
+     *                   string in case of IllegalArgumentException
+     * @param executor the Executor for the listener
+     * @param listener the listener to add
+     * @param listeners the list of listener informations, can be null if not instantiated yet
+     * @param dispatchStub the stub that receives the events to be forwarded to the listeners,
+     *                    can be null if not instantiated yet
+     * @param newStub the function to create a new stub if needed
+     * @param registerStub the function for the stub registration if needed
+     * @param <T> the type of the listener interface
+     * @param <S> the type of the event receiver stub
+     * @return a pair of the listener list and the event receiver stub which may have been
+     *         initialized if needed (e.g. on the first ever addition of a listener)
+     */
+    static <T, S> Pair<ArrayList<ListenerInfo<T>>, S> addListener(String methodName,
+            @NonNull Executor executor,
+            @NonNull T listener,
+            @Nullable ArrayList<ListenerInfo<T>> listeners,
+            @Nullable S dispatchStub,
+            @NonNull java.util.function.Supplier<S> newStub,
+            @NonNull java.util.function.Consumer<S> registerStub) {
+        Objects.requireNonNull(executor);
+        Objects.requireNonNull(listener);
+
+        if (hasListener(listener, listeners)) {
+            throw new IllegalArgumentException("attempt to call " + methodName
+                    + "on a previously registered listener");
+        }
+        // lazy initialization of the list of strategy-preferred device listener
+        if (listeners == null) {
+            listeners = new ArrayList<>();
+        }
+        if (listeners.size() == 0) {
+            // register binder for callbacks
+            if (dispatchStub == null) {
+                try {
+                    dispatchStub = newStub.get();
+                } catch (Exception e) {
+                    Log.e(TAG, "Exception while creating stub in " + methodName, e);
+                    return new Pair<>(null, null);
+                }
+            }
+            registerStub.accept(dispatchStub);
+        }
+        listeners.add(new ListenerInfo<T>(listener, executor));
+        return new Pair(listeners, dispatchStub);
+    }
+
+    /**
+     * Removes a listener from the list of listeners.
+     * This method handles the freeing of both the list of listeners and the stub
+     * used to receive the events that will be forwarded to the listener,see the returned pair
+     * for the updated references.
+     * @param methodName the name of the method calling this, for inclusion in the
+     *                   string in case of IllegalArgumentException
+     * @param listener the listener to remove
+     * @param listeners the list of listener informations, can be null if not instantiated yet
+     * @param dispatchStub the stub that receives the events to be forwarded to the listeners,
+     *                    can be null if not instantiated yet
+     * @param unregisterStub the function to unregister the stub if needed
+     * @param <T> the type of the listener interface
+     * @param <S> the type of the event receiver stub
+     * @return a pair of the listener list and the event receiver stub which may have been
+     *         changed if needed (e.g. on the removal of the last listener)
+     */
+    static <T, S> Pair<ArrayList<ListenerInfo<T>>, S> removeListener(String methodName,
+            @NonNull T listener,
+            @Nullable ArrayList<ListenerInfo<T>> listeners,
+            @Nullable S dispatchStub,
+            @NonNull java.util.function.Consumer<S> unregisterStub) {
+        Objects.requireNonNull(listener);
+
+        if (!removeListener(listener, listeners)) {
+            throw new IllegalArgumentException("attempt to call " + methodName
+                    + "on an unregistered listener");
+        }
+        if (listeners.size() == 0) {
+            unregisterStub.accept(dispatchStub);
+            return new Pair<>(null, null);
+        } else {
+            return new Pair<>(listeners, dispatchStub);
+        }
+    }
+
+    interface CallbackMethod<T> {
+        void callbackMethod(T listener);
+    }
+
+    /**
+     * Exercise the callback of the listeners
+     * @param listeners the list of listeners
+     * @param listenerLock the lock guarding the list of listeners
+     * @param callback the function to call for each listener
+     * @param <T>  the type of the listener interface
+     */
+    static <T> void callListeners(
+            @Nullable ArrayList<ListenerInfo<T>> listeners,
+            @NonNull Object listenerLock,
+            @NonNull CallbackMethod<T> callback) {
+        Objects.requireNonNull(listenerLock);
+        // make a shallow copy of listeners so callback is not executed under lock
+        final ArrayList<ListenerInfo<T>> listenersShallowCopy;
+        synchronized (listenerLock) {
+            if (listeners == null || listeners.size() == 0) {
+                return;
+            }
+            listenersShallowCopy = (ArrayList<ListenerInfo<T>>) listeners.clone();
+        }
+        try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
+            for (ListenerInfo<T> info : listenersShallowCopy) {
+                info.mExecutor.execute(() -> callback.callbackMethod(info.mListener));
+            }
+        }
+
+    }
+}
diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java
index bac44ad..e979a1b5 100644
--- a/media/java/android/media/Image.java
+++ b/media/java/android/media/Image.java
@@ -163,6 +163,14 @@
      *      {@link android.graphics.BitmapFactory#decodeByteArray BitmapFactory#decodeByteArray}.
      *   </td>
      * </tr>
+     * <tr>
+     *   <td>{@link android.graphics.ImageFormat#YCBCR_P010 YCBCR_P010}</td>
+     *   <td>1</td>
+     *   <td>P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane
+     *     followed by a Wx(H/2) CbCr plane. Each sample is represented by a 16-bit
+     *     little-endian value, with the lower 6 bits set to zero.
+     *   </td>
+     * </tr>
      * </table>
      *
      * @see android.graphics.ImageFormat
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 4daedfc..939b679 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -5106,7 +5106,6 @@
         public MediaImage(
                 @NonNull ByteBuffer buffer, @NonNull ByteBuffer info, boolean readOnly,
                 long timestamp, int xOffset, int yOffset, @Nullable Rect cropRect) {
-            mFormat = ImageFormat.YUV_420_888;
             mTimestamp = timestamp;
             mIsImageValid = true;
             mIsReadOnly = buffer.isReadOnly();
@@ -5119,6 +5118,11 @@
 
             mBufferContext = 0;
 
+            int cbPlaneOffset = -1;
+            int crPlaneOffset = -1;
+            int planeOffsetInc = -1;
+            int pixelStride = -1;
+
             // read media-info.  See MediaImage2
             if (info.remaining() == 104) {
                 int type = info.getInt();
@@ -5136,14 +5140,27 @@
                             "unsupported size: " + mWidth + "x" + mHeight);
                 }
                 int bitDepth = info.getInt();
-                if (bitDepth != 8) {
+                if (bitDepth != 8 && bitDepth != 10) {
                     throw new UnsupportedOperationException("unsupported bit depth: " + bitDepth);
                 }
                 int bitDepthAllocated = info.getInt();
-                if (bitDepthAllocated != 8) {
+                if (bitDepthAllocated != 8 && bitDepthAllocated != 16) {
                     throw new UnsupportedOperationException(
                             "unsupported allocated bit depth: " + bitDepthAllocated);
                 }
+                if (bitDepth == 8 && bitDepthAllocated == 8) {
+                    mFormat = ImageFormat.YUV_420_888;
+                    planeOffsetInc = 1;
+                    pixelStride = 2;
+                } else if (bitDepth == 10 && bitDepthAllocated == 16) {
+                    mFormat = ImageFormat.YCBCR_P010;
+                    planeOffsetInc = 2;
+                    pixelStride = 4;
+                } else {
+                    throw new UnsupportedOperationException("couldn't infer ImageFormat"
+                      + " bitDepth: " + bitDepth + " bitDepthAllocated: " + bitDepthAllocated);
+                }
+
                 mPlanes = new MediaPlane[numPlanes];
                 for (int ix = 0; ix < numPlanes; ix++) {
                     int planeOffset = info.getInt();
@@ -5165,12 +5182,31 @@
                     buffer.limit(buffer.position() + Utils.divUp(bitDepth, 8)
                             + (mHeight / vert - 1) * rowInc + (mWidth / horiz - 1) * colInc);
                     mPlanes[ix] = new MediaPlane(buffer.slice(), rowInc, colInc);
+                    if ((mFormat == ImageFormat.YUV_420_888 || mFormat == ImageFormat.YCBCR_P010)
+                            && ix == 1) {
+                        cbPlaneOffset = planeOffset;
+                    } else if ((mFormat == ImageFormat.YUV_420_888
+                            || mFormat == ImageFormat.YCBCR_P010) && ix == 2) {
+                        crPlaneOffset = planeOffset;
+                    }
                 }
             } else {
                 throw new UnsupportedOperationException(
                         "unsupported info length: " + info.remaining());
             }
 
+            // Validate chroma semiplanerness.
+            if (mFormat == ImageFormat.YCBCR_P010) {
+                if (crPlaneOffset != cbPlaneOffset + planeOffsetInc) {
+                    throw new UnsupportedOperationException("Invalid plane offsets"
+                    + " cbPlaneOffset: " + cbPlaneOffset + " crPlaneOffset: " + crPlaneOffset);
+                }
+                if (mPlanes[1].getPixelStride() != pixelStride
+                        || mPlanes[2].getPixelStride() != pixelStride) {
+                    throw new UnsupportedOperationException("Invalid pixelStride");
+                }
+            }
+
             if (cropRect == null) {
                 cropRect = new Rect(0, 0, mWidth, mHeight);
             }
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index 374cc75..3c152fb 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -426,6 +426,12 @@
         /** @deprecated Use {@link #COLOR_Format32bitABGR8888}. */
         public static final int COLOR_Format24BitABGR6666           = 43;
 
+        /** @hide
+         * P010 is a 4:2:0 YCbCr semiplanar format comprised of a WxH Y plane
+         * followed by a Wx(H/2) CbCr plane. Each sample is represented by a 16-bit
+         * little-endian value, with the lower 6 bits set to zero. */
+        public static final int COLOR_FormatYUVP010                 = 54;
+
         /** @deprecated Use {@link #COLOR_FormatYUV420Flexible}. */
         public static final int COLOR_TI_FormatYUV420PackedSemiPlanar = 0x7f000100;
         // COLOR_FormatSurface indicates that the data will be a GraphicBuffer metadata reference.
diff --git a/media/java/android/media/Spatializer.java b/media/java/android/media/Spatializer.java
index e6fff39..c0793ec 100644
--- a/media/java/android/media/Spatializer.java
+++ b/media/java/android/media/Spatializer.java
@@ -22,11 +22,14 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.media.CallbackUtil.ListenerInfo;
 import android.media.permission.ClearCallingIdentityContext;
 import android.media.permission.SafeCloseable;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.Pair;
 
 import com.android.internal.annotations.GuardedBy;
 
@@ -373,32 +376,15 @@
     public void addOnSpatializerStateChangedListener(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull OnSpatializerStateChangedListener listener) {
-        Objects.requireNonNull(executor);
-        Objects.requireNonNull(listener);
         synchronized (mStateListenerLock) {
-            if (hasSpatializerStateListener(listener)) {
-                throw new IllegalArgumentException(
-                        "Called addOnSpatializerStateChangedListener() "
-                        + "on a previously registered listener");
-            }
-            // lazy initialization of the list of strategy-preferred device listener
-            if (mStateListeners == null) {
-                mStateListeners = new ArrayList<>();
-            }
-            mStateListeners.add(new StateListenerInfo(listener, executor));
-            if (mStateListeners.size() == 1) {
-                // register binder for callbacks
-                if (mInfoDispatcherStub == null) {
-                    mInfoDispatcherStub =
-                            new SpatializerInfoDispatcherStub();
-                }
-                try {
-                    mAm.getService().registerSpatializerCallback(
-                            mInfoDispatcherStub);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
+            final Pair<ArrayList<ListenerInfo<OnSpatializerStateChangedListener>>,
+                    SpatializerInfoDispatcherStub> res =
+                    CallbackUtil.addListener("addOnSpatializerStateChangedListener",
+                            executor, listener, mStateListeners, mInfoDispatcherStub,
+                            () -> new SpatializerInfoDispatcherStub(),
+                            stub -> stub.register(true));
+            mStateListeners = res.first;
+            mInfoDispatcherStub = res.second;
         }
     }
 
@@ -410,24 +396,14 @@
      */
     public void removeOnSpatializerStateChangedListener(
             @NonNull OnSpatializerStateChangedListener listener) {
-        Objects.requireNonNull(listener);
         synchronized (mStateListenerLock) {
-            if (!removeStateListener(listener)) {
-                throw new IllegalArgumentException(
-                        "Called removeOnSpatializerStateChangedListener() "
-                        + "on an unregistered listener");
-            }
-            if (mStateListeners.size() == 0) {
-                // unregister binder for callbacks
-                try {
-                    mAm.getService().unregisterSpatializerCallback(mInfoDispatcherStub);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                } finally {
-                    mInfoDispatcherStub = null;
-                    mStateListeners = null;
-                }
-            }
+            final Pair<ArrayList<ListenerInfo<OnSpatializerStateChangedListener>>,
+                    SpatializerInfoDispatcherStub> res =
+                    CallbackUtil.removeListener("removeOnSpatializerStateChangedListener",
+                            listener, mStateListeners, mInfoDispatcherStub,
+                            stub -> stub.register(false));
+            mStateListeners = res.first;
+            mInfoDispatcherStub = res.second;
         }
     }
 
@@ -489,93 +465,41 @@
      * List is lazy-initialized on first registration
      */
     @GuardedBy("mStateListenerLock")
-    private @Nullable ArrayList<StateListenerInfo> mStateListeners;
+    private @Nullable ArrayList<ListenerInfo<OnSpatializerStateChangedListener>> mStateListeners;
 
     @GuardedBy("mStateListenerLock")
     private @Nullable SpatializerInfoDispatcherStub mInfoDispatcherStub;
 
     private final class SpatializerInfoDispatcherStub extends ISpatializerCallback.Stub {
+        public void register(boolean register) {
+            try {
+                if (register) {
+                    mAm.getService().registerSpatializerCallback(this);
+                } else {
+                    mAm.getService().unregisterSpatializerCallback(this);
+                }
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
+            }
+        }
+
         @Override
+        @SuppressLint("GuardedBy") // lock applied inside callListeners method
         public void dispatchSpatializerEnabledChanged(boolean enabled) {
-            // make a shallow copy of listeners so callback is not executed under lock
-            final ArrayList<StateListenerInfo> stateListeners;
-            synchronized (mStateListenerLock) {
-                if (mStateListeners == null || mStateListeners.size() == 0) {
-                    return;
-                }
-                stateListeners = (ArrayList<StateListenerInfo>) mStateListeners.clone();
-            }
-            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
-                for (StateListenerInfo info : stateListeners) {
-                    info.mExecutor.execute(() ->
-                            info.mListener.onSpatializerEnabledChanged(Spatializer.this, enabled));
-                }
-            }
+            CallbackUtil.callListeners(mStateListeners, mStateListenerLock,
+                    (listener) -> listener.onSpatializerEnabledChanged(
+                            Spatializer.this, enabled));
         }
 
         @Override
+        @SuppressLint("GuardedBy") // lock applied inside callListeners method
         public void dispatchSpatializerAvailableChanged(boolean available) {
-            // make a shallow copy of listeners so callback is not executed under lock
-            final ArrayList<StateListenerInfo> stateListeners;
-            synchronized (mStateListenerLock) {
-                if (mStateListeners == null || mStateListeners.size() == 0) {
-                    return;
-                }
-                stateListeners = (ArrayList<StateListenerInfo>) mStateListeners.clone();
-            }
-            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
-                for (StateListenerInfo info : stateListeners) {
-                    info.mExecutor.execute(() ->
-                            info.mListener.onSpatializerAvailableChanged(
-                                    Spatializer.this, available));
-                }
-            }
+            CallbackUtil.callListeners(mStateListeners, mStateListenerLock,
+                    (listener) -> listener.onSpatializerAvailableChanged(
+                            Spatializer.this, available));
         }
     }
 
-    private static class StateListenerInfo {
-        final @NonNull OnSpatializerStateChangedListener mListener;
-        final @NonNull Executor mExecutor;
-
-        StateListenerInfo(@NonNull OnSpatializerStateChangedListener listener,
-                @NonNull Executor exe) {
-            mListener = listener;
-            mExecutor = exe;
-        }
-    }
-
-    @GuardedBy("mStateListenerLock")
-    private boolean hasSpatializerStateListener(OnSpatializerStateChangedListener listener) {
-        return getStateListenerInfo(listener) != null;
-    }
-
-    @GuardedBy("mStateListenerLock")
-    private @Nullable StateListenerInfo getStateListenerInfo(
-            OnSpatializerStateChangedListener listener) {
-        if (mStateListeners == null) {
-            return null;
-        }
-        for (StateListenerInfo info : mStateListeners) {
-            if (info.mListener == listener) {
-                return info;
-            }
-        }
-        return null;
-    }
-
-    @GuardedBy("mStateListenerLock")
-    /**
-     * @return true if the listener was removed from the list
-     */
-    private boolean removeStateListener(OnSpatializerStateChangedListener listener) {
-        final StateListenerInfo infoToRemove = getStateListenerInfo(listener);
-        if (infoToRemove != null) {
-            mStateListeners.remove(infoToRemove);
-            return true;
-        }
-        return false;
-    }
-
 
     /**
      * @hide
@@ -688,33 +612,15 @@
     public void addOnHeadTrackingModeChangedListener(
             @NonNull @CallbackExecutor Executor executor,
             @NonNull OnHeadTrackingModeChangedListener listener) {
-        Objects.requireNonNull(executor);
-        Objects.requireNonNull(listener);
         synchronized (mHeadTrackingListenerLock) {
-            if (hasListener(listener, mHeadTrackingListeners)) {
-                throw new IllegalArgumentException(
-                        "Called addOnHeadTrackingModeChangedListener() "
-                                + "on a previously registered listener");
-            }
-            // lazy initialization of the list of strategy-preferred device listener
-            if (mHeadTrackingListeners == null) {
-                mHeadTrackingListeners = new ArrayList<>();
-            }
-            mHeadTrackingListeners.add(
-                    new ListenerInfo<OnHeadTrackingModeChangedListener>(listener, executor));
-            if (mHeadTrackingListeners.size() == 1) {
-                // register binder for callbacks
-                if (mHeadTrackingDispatcherStub == null) {
-                    mHeadTrackingDispatcherStub =
-                            new SpatializerHeadTrackingDispatcherStub();
-                }
-                try {
-                    mAm.getService().registerSpatializerHeadTrackingCallback(
-                            mHeadTrackingDispatcherStub);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                }
-            }
+            final Pair<ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>>,
+                    SpatializerHeadTrackingDispatcherStub> res = CallbackUtil.addListener(
+                        "addOnHeadTrackingModeChangedListener", executor, listener,
+                        mHeadTrackingListeners, mHeadTrackingDispatcherStub,
+                        () -> new SpatializerHeadTrackingDispatcherStub(),
+                        stub -> stub.register(true));
+            mHeadTrackingListeners = res.first;
+            mHeadTrackingDispatcherStub = res.second;
         }
     }
 
@@ -728,25 +634,14 @@
     @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
     public void removeOnHeadTrackingModeChangedListener(
             @NonNull OnHeadTrackingModeChangedListener listener) {
-        Objects.requireNonNull(listener);
         synchronized (mHeadTrackingListenerLock) {
-            if (!removeListener(listener, mHeadTrackingListeners)) {
-                throw new IllegalArgumentException(
-                        "Called removeOnHeadTrackingModeChangedListener() "
-                                + "on an unregistered listener");
-            }
-            if (mHeadTrackingListeners.size() == 0) {
-                // unregister binder for callbacks
-                try {
-                    mAm.getService().unregisterSpatializerHeadTrackingCallback(
-                            mHeadTrackingDispatcherStub);
-                } catch (RemoteException e) {
-                    throw e.rethrowFromSystemServer();
-                } finally {
-                    mHeadTrackingDispatcherStub = null;
-                    mHeadTrackingListeners = null;
-                }
-            }
+            final Pair<ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>>,
+                    SpatializerHeadTrackingDispatcherStub> res = CallbackUtil.removeListener(
+                        "removeOnHeadTrackingModeChangedListener", listener,
+                        mHeadTrackingListeners, mHeadTrackingDispatcherStub,
+                        stub -> stub.register(false));
+            mHeadTrackingListeners = res.first;
+            mHeadTrackingDispatcherStub = res.second;
         }
     }
 
@@ -931,45 +826,6 @@
     }
 
     //-----------------------------------------------------------------------------
-    // callback helper definitions
-
-    private static class ListenerInfo<T> {
-        final @NonNull T mListener;
-        final @NonNull Executor mExecutor;
-
-        ListenerInfo(T listener, Executor exe) {
-            mListener = listener;
-            mExecutor = exe;
-        }
-    }
-
-    private static <T> ListenerInfo<T> getListenerInfo(
-            T listener, ArrayList<ListenerInfo<T>> listeners) {
-        if (listeners == null) {
-            return null;
-        }
-        for (ListenerInfo<T> info : listeners) {
-            if (info.mListener == listener) {
-                return info;
-            }
-        }
-        return null;
-    }
-
-    private static <T> boolean hasListener(T listener, ArrayList<ListenerInfo<T>> listeners) {
-        return getListenerInfo(listener, listeners) != null;
-    }
-
-    private static <T> boolean removeListener(T listener, ArrayList<ListenerInfo<T>> listeners) {
-        final ListenerInfo<T> infoToRemove = getListenerInfo(listener, listeners);
-        if (infoToRemove != null) {
-            listeners.remove(infoToRemove);
-            return true;
-        }
-        return false;
-    }
-
-    //-----------------------------------------------------------------------------
     // head tracking callback management and stub
 
     private final Object mHeadTrackingListenerLock = new Object();
@@ -986,42 +842,31 @@
 
     private final class SpatializerHeadTrackingDispatcherStub
             extends ISpatializerHeadTrackingModeCallback.Stub {
-        @Override
-        public void dispatchSpatializerActualHeadTrackingModeChanged(int mode) {
-            // make a shallow copy of listeners so callback is not executed under lock
-            final ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>> headTrackingListeners;
-            synchronized (mHeadTrackingListenerLock) {
-                if (mHeadTrackingListeners == null || mHeadTrackingListeners.size() == 0) {
-                    return;
+        public void register(boolean register) {
+            try {
+                if (register) {
+                    mAm.getService().registerSpatializerHeadTrackingCallback(this);
+                } else {
+                    mAm.getService().unregisterSpatializerHeadTrackingCallback(this);
                 }
-                headTrackingListeners = (ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>>)
-                        mHeadTrackingListeners.clone();
-            }
-            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
-                for (ListenerInfo<OnHeadTrackingModeChangedListener> info : headTrackingListeners) {
-                    info.mExecutor.execute(() -> info.mListener
-                            .onHeadTrackingModeChanged(Spatializer.this, mode));
-                }
+            } catch (RemoteException e) {
+                e.rethrowFromSystemServer();
             }
         }
 
         @Override
+        @SuppressLint("GuardedBy") // lock applied inside callListeners method
+        public void dispatchSpatializerActualHeadTrackingModeChanged(int mode) {
+            CallbackUtil.callListeners(mHeadTrackingListeners, mHeadTrackingListenerLock,
+                    (listener) -> listener.onHeadTrackingModeChanged(Spatializer.this, mode));
+        }
+
+        @Override
+        @SuppressLint("GuardedBy") // lock applied inside callListeners method
         public void dispatchSpatializerDesiredHeadTrackingModeChanged(int mode) {
-            // make a shallow copy of listeners so callback is not executed under lock
-            final ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>> headTrackingListeners;
-            synchronized (mHeadTrackingListenerLock) {
-                if (mHeadTrackingListeners == null || mHeadTrackingListeners.size() == 0) {
-                    return;
-                }
-                headTrackingListeners = (ArrayList<ListenerInfo<OnHeadTrackingModeChangedListener>>)
-                        mHeadTrackingListeners.clone();
-            }
-            try (SafeCloseable ignored = ClearCallingIdentityContext.create()) {
-                for (ListenerInfo<OnHeadTrackingModeChangedListener> info : headTrackingListeners) {
-                    info.mExecutor.execute(() -> info.mListener
-                            .onDesiredHeadTrackingModeChanged(Spatializer.this, mode));
-                }
-            }
+            CallbackUtil.callListeners(mHeadTrackingListeners, mHeadTrackingListenerLock,
+                    (listener) -> listener.onDesiredHeadTrackingModeChanged(
+                            Spatializer.this, mode));
         }
     }
 
diff --git a/media/java/android/media/tv/BroadcastInfoRequest.java b/media/java/android/media/tv/BroadcastInfoRequest.java
index 6077f04..4d8eda1 100644
--- a/media/java/android/media/tv/BroadcastInfoRequest.java
+++ b/media/java/android/media/tv/BroadcastInfoRequest.java
@@ -22,12 +22,21 @@
 import android.annotation.NonNull;
 
 /** @hide */
-public final class BroadcastInfoRequest implements Parcelable {
+public abstract class BroadcastInfoRequest implements Parcelable {
+    protected static final int PARCEL_TOKEN_TS_REQUEST = 1;
+
     public static final @NonNull Parcelable.Creator<BroadcastInfoRequest> CREATOR =
             new Parcelable.Creator<BroadcastInfoRequest>() {
                 @Override
                 public BroadcastInfoRequest createFromParcel(Parcel source) {
-                    return new BroadcastInfoRequest(source);
+                    int token = source.readInt();
+                    switch (token) {
+                        case PARCEL_TOKEN_TS_REQUEST:
+                            return TsRequest.createFromParcelBody(source);
+                        default:
+                            throw new IllegalStateException(
+                                    "Unexpected broadcast info request type token in parcel.");
+                    }
                 }
 
                 @Override
@@ -42,10 +51,14 @@
         this.requestId = requestId;
     }
 
-    private BroadcastInfoRequest(Parcel source) {
+    protected BroadcastInfoRequest(Parcel source) {
         requestId = source.readInt();
     }
 
+    public int getRequestId() {
+        return requestId;
+    }
+
     @Override
     public int describeContents() {
         return 0;
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt b/media/java/android/media/tv/TsRequest.aidl
similarity index 84%
copy from packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
copy to media/java/android/media/tv/TsRequest.aidl
index bacc66b..0abc7ec 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
+++ b/media/java/android/media/tv/TsRequest.aidl
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.flags
+package android.media.tv;
 
-interface FlagWriter {
-    fun setEnabled(key: Int, value: Boolean) {}
-}
\ No newline at end of file
+parcelable TsRequest;
diff --git a/media/java/android/media/tv/TsRequest.java b/media/java/android/media/tv/TsRequest.java
new file mode 100644
index 0000000..3690d05
--- /dev/null
+++ b/media/java/android/media/tv/TsRequest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 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 android.media.tv;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/** @hide */
+public class TsRequest extends BroadcastInfoRequest implements Parcelable {
+    public static final @NonNull Parcelable.Creator<TsRequest> CREATOR =
+            new Parcelable.Creator<TsRequest>() {
+                @Override
+                public TsRequest createFromParcel(Parcel source) {
+                    source.readInt();
+                    return createFromParcelBody(source);
+                }
+
+                @Override
+                public TsRequest[] newArray(int size) {
+                    return new TsRequest[size];
+                }
+            };
+
+    int tsPid;
+
+    public static TsRequest createFromParcelBody(Parcel in) {
+        return new TsRequest(in);
+    }
+
+    public TsRequest(int requestId, int tsPid) {
+        super(requestId);
+        this.tsPid = tsPid;
+    }
+
+    protected TsRequest(Parcel source) {
+        super(source);
+        tsPid = source.readInt();
+    }
+
+    public int getTsPid() {
+        return tsPid;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeInt(PARCEL_TOKEN_TS_REQUEST);
+        super.writeToParcel(dest, flags);
+        dest.writeInt(tsPid);
+    }
+}
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index f22b7dc..0461f0a 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -28,6 +28,7 @@
 import android.content.Intent;
 import android.graphics.Rect;
 import android.media.PlaybackParams;
+import android.media.tv.interactive.TvIAppManager;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -2073,6 +2074,8 @@
         // @GuardedBy("mMetadataLock")
         private int mVideoHeight;
 
+        private TvIAppManager.Session mIAppSession;
+
         private Session(IBinder token, InputChannel channel, ITvInputManager service, int userId,
                 int seq, SparseArray<SessionCallbackRecord> sessionCallbackRecordMap) {
             mToken = token;
@@ -2083,6 +2086,14 @@
             mSessionCallbackRecordMap = sessionCallbackRecordMap;
         }
 
+        public TvIAppManager.Session getIAppSession() {
+            return mIAppSession;
+        }
+
+        public void setIAppSession(TvIAppManager.Session IAppSession) {
+            this.mIAppSession = IAppSession;
+        }
+
         /**
          * Releases this session.
          */
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index f312f64..d285b13 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -53,6 +53,7 @@
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.View;
+import android.view.ViewRootImpl;
 import android.view.WindowManager;
 import android.view.accessibility.CaptioningManager;
 import android.widget.FrameLayout;
@@ -1581,7 +1582,8 @@
                 return TvInputManager.Session.DISPATCH_NOT_HANDLED;
             }
             if (!mOverlayViewContainer.hasWindowFocus()) {
-                mOverlayViewContainer.getViewRootImpl().windowFocusChanged(true, true);
+                ViewRootImpl viewRoot = mOverlayViewContainer.getViewRootImpl();
+                viewRoot.windowFocusChanged(true);
             }
             if (isNavigationKey && mOverlayViewContainer.hasFocusable()) {
                 // If mOverlayView has focusable views, navigation key events should be always
diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java
index b1baf94..6994d28 100644
--- a/media/java/android/media/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -34,6 +34,8 @@
 import android.media.tv.TvInputManager.Session;
 import android.media.tv.TvInputManager.Session.FinishedInputEventCallback;
 import android.media.tv.TvInputManager.SessionCallback;
+import android.media.tv.interactive.TvIAppManager;
+import android.media.tv.interactive.TvIAppView;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -197,6 +199,11 @@
         mCallback = callback;
     }
 
+    /** @hide */
+    public Session getInputSession() {
+        return mSession;
+    }
+
     /**
      * Sets this as the main {@link TvView}.
      *
diff --git a/media/java/android/media/tv/interactive/ITvIAppClient.aidl b/media/java/android/media/tv/interactive/ITvIAppClient.aidl
index 0dd64b8..dabea30 100644
--- a/media/java/android/media/tv/interactive/ITvIAppClient.aidl
+++ b/media/java/android/media/tv/interactive/ITvIAppClient.aidl
@@ -16,13 +16,15 @@
 
 package android.media.tv.interactive;
 
+import android.view.InputChannel;
+
 /**
  * Interface a client of the ITvIAppManager implements, to identify itself and receive information
  * about changes to the state of each TV interactive application service.
  * @hide
  */
 oneway interface ITvIAppClient {
-    void onSessionCreated(in String iAppServiceId, IBinder token, int seq);
+    void onSessionCreated(in String iAppServiceId, IBinder token, in InputChannel channel, int seq);
     void onSessionReleased(int seq);
     void onLayoutSurface(int left, int top, int right, int bottom, int seq);
 }
\ No newline at end of file
diff --git a/media/java/android/media/tv/interactive/ITvIAppManager.aidl b/media/java/android/media/tv/interactive/ITvIAppManager.aidl
index c7b08d5..104efe6 100644
--- a/media/java/android/media/tv/interactive/ITvIAppManager.aidl
+++ b/media/java/android/media/tv/interactive/ITvIAppManager.aidl
@@ -17,6 +17,8 @@
 package android.media.tv.interactive;
 
 import android.media.tv.interactive.ITvIAppClient;
+import android.media.tv.interactive.ITvIAppManagerCallback;
+import android.media.tv.interactive.TvIAppInfo;
 import android.view.Surface;
 
 /**
@@ -24,6 +26,7 @@
  * @hide
  */
 interface ITvIAppManager {
+    List<TvIAppInfo> getTvIAppServiceList(int userId);
     void startIApp(in IBinder sessionToken, int userId);
     void createSession(
             in ITvIAppClient client, in String iAppServiceId, int type, int seq, int userId);
@@ -31,4 +34,7 @@
     void setSurface(in IBinder sessionToken, in Surface surface, int userId);
     void dispatchSurfaceChanged(in IBinder sessionToken, int format, int width, int height,
             int userId);
+
+    void registerCallback(in ITvIAppManagerCallback callback, int userId);
+    void unregisterCallback(in ITvIAppManagerCallback callback, int userId);
 }
\ No newline at end of file
diff --git a/media/java/android/media/tv/interactive/ITvIAppManagerCallback.aidl b/media/java/android/media/tv/interactive/ITvIAppManagerCallback.aidl
new file mode 100644
index 0000000..77a09b7
--- /dev/null
+++ b/media/java/android/media/tv/interactive/ITvIAppManagerCallback.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 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 android.media.tv.interactive;
+
+import android.media.tv.interactive.TvIAppInfo;
+
+/**
+ * Interface to receive callbacks from ITvIAppManager regardless of sessions.
+ * @hide
+ */
+interface ITvIAppManagerCallback {
+    void onIAppServiceAdded(in String iAppServiceId);
+    void onIAppServiceRemoved(in String iAppServiceId);
+    void onIAppServiceUpdated(in String iAppServiceId);
+    void onTvIAppInfoUpdated(in TvIAppInfo tvIAppInfo);
+}
\ No newline at end of file
diff --git a/media/java/android/media/tv/interactive/ITvIAppService.aidl b/media/java/android/media/tv/interactive/ITvIAppService.aidl
index c4f82eb..1dee9cc 100644
--- a/media/java/android/media/tv/interactive/ITvIAppService.aidl
+++ b/media/java/android/media/tv/interactive/ITvIAppService.aidl
@@ -16,7 +16,9 @@
 
 package android.media.tv.interactive;
 
+import android.media.tv.interactive.ITvIAppServiceCallback;
 import android.media.tv.interactive.ITvIAppSessionCallback;
+import android.view.InputChannel;
 
 /**
  * Top-level interface to a TV IApp component (implemented in a Service). It's used for
@@ -24,5 +26,8 @@
  * @hide
  */
 oneway interface ITvIAppService {
-    void createSession(in ITvIAppSessionCallback callback, in String iAppServiceId, int type);
+    void registerCallback(in ITvIAppServiceCallback callback);
+    void unregisterCallback(in ITvIAppServiceCallback callback);
+    void createSession(in InputChannel channel, in ITvIAppSessionCallback callback,
+            in String iAppServiceId, int type);
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt b/media/java/android/media/tv/interactive/TvIAppInfo.aidl
similarity index 84%
rename from packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
rename to media/java/android/media/tv/interactive/TvIAppInfo.aidl
index bacc66b..6041460 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
+++ b/media/java/android/media/tv/interactive/TvIAppInfo.aidl
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.flags
+package android.media.tv.interactive;
 
-interface FlagWriter {
-    fun setEnabled(key: Int, value: Boolean) {}
-}
\ No newline at end of file
+parcelable TvIAppInfo;
\ No newline at end of file
diff --git a/media/java/android/media/tv/interactive/TvIAppInfo.java b/media/java/android/media/tv/interactive/TvIAppInfo.java
new file mode 100644
index 0000000..de3a47e
--- /dev/null
+++ b/media/java/android/media/tv/interactive/TvIAppInfo.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2021 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 android.media.tv.interactive;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class is used to specify meta information of a TV interactive app.
+ * @hide
+ */
+public final class TvIAppInfo implements Parcelable {
+    private static final boolean DEBUG = false;
+    private static final String TAG = "TvIAppInfo";
+
+    private final ResolveInfo mService;
+    private final String mId;
+    private List<String> mTypes = new ArrayList<>();
+
+    private TvIAppInfo(ResolveInfo service, String id, List<String> types) {
+        mService = service;
+        mId = id;
+        mTypes = types;
+    }
+
+    protected TvIAppInfo(Parcel in) {
+        mService = ResolveInfo.CREATOR.createFromParcel(in);
+        mId = in.readString();
+        in.readStringList(mTypes);
+    }
+
+    public static final Creator<TvIAppInfo> CREATOR = new Creator<TvIAppInfo>() {
+        @Override
+        public TvIAppInfo createFromParcel(Parcel in) {
+            return new TvIAppInfo(in);
+        }
+
+        @Override
+        public TvIAppInfo[] newArray(int size) {
+            return new TvIAppInfo[size];
+        }
+    };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        mService.writeToParcel(dest, flags);
+        dest.writeString(mId);
+        dest.writeStringList(mTypes);
+    }
+
+    public String getId() {
+        return mId;
+    }
+
+    /**
+     * Returns the component of the TV IApp service.
+     * @hide
+     */
+    public ComponentName getComponent() {
+        return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name);
+    }
+
+    /**
+     * Returns the information of the service that implements this TV IApp service.
+     */
+    public ServiceInfo getServiceInfo() {
+        return mService.serviceInfo;
+    }
+
+    /**
+     * A convenience builder for creating {@link TvIAppInfo} objects.
+     */
+    public static final class Builder {
+        private static final String XML_START_TAG_NAME = "tv-iapp";
+        private final Context mContext;
+        private final ResolveInfo mResolveInfo;
+        private final List<String> mTypes = new ArrayList<>();
+
+        /**
+         * Constructs a new builder for {@link TvIAppInfo}.
+         *
+         * @param context A Context of the application package implementing this class.
+         * @param component The name of the application component to be used for the
+         *                  {@link TvIAppService}.
+         */
+        public Builder(Context context, ComponentName component) {
+            if (context == null) {
+                throw new IllegalArgumentException("context cannot be null.");
+            }
+            Intent intent = new Intent(TvIAppService.SERVICE_INTERFACE).setComponent(component);
+            mResolveInfo = context.getPackageManager().resolveService(intent,
+                    PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
+            if (mResolveInfo == null) {
+                throw new IllegalArgumentException("Invalid component. Can't find the service.");
+            }
+            mContext = context;
+        }
+
+        /**
+         * Creates a {@link TvIAppInfo} instance with the specified fields. Most of the information
+         * is obtained by parsing the AndroidManifest and {@link TvIAppService#SERVICE_META_DATA}
+         * for the {@link TvIAppService} this TV IApp implements.
+         *
+         * @return TvIAppInfo containing information about this TV IApp service.
+         */
+        public TvIAppInfo build() {
+            ComponentName componentName = new ComponentName(mResolveInfo.serviceInfo.packageName,
+                    mResolveInfo.serviceInfo.name);
+            String id;
+            id = generateIAppServiceId(componentName);
+            parseServiceMetadata();
+            return new TvIAppInfo(mResolveInfo, id, mTypes);
+        }
+
+        private static String generateIAppServiceId(ComponentName name) {
+            return name.flattenToShortString();
+        }
+
+        private void parseServiceMetadata() {
+            ServiceInfo si = mResolveInfo.serviceInfo;
+            PackageManager pm = mContext.getPackageManager();
+            try (XmlResourceParser parser =
+                         si.loadXmlMetaData(pm, TvIAppService.SERVICE_META_DATA)) {
+                if (parser == null) {
+                    throw new IllegalStateException("No " + TvIAppService.SERVICE_META_DATA
+                            + " meta-data found for " + si.name);
+                }
+
+                Resources res = pm.getResourcesForApplication(si.applicationInfo);
+                AttributeSet attrs = Xml.asAttributeSet(parser);
+
+                int type;
+                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                        && type != XmlPullParser.START_TAG) {
+                    // move to the START_TAG
+                }
+
+                String nodeName = parser.getName();
+                if (!XML_START_TAG_NAME.equals(nodeName)) {
+                    throw new IllegalStateException("Meta-data does not start with "
+                            + XML_START_TAG_NAME + " tag for " + si.name);
+                }
+
+                TypedArray sa = res.obtainAttributes(attrs,
+                        com.android.internal.R.styleable.TvIAppService);
+                CharSequence[] types = sa.getTextArray(
+                        com.android.internal.R.styleable.TvIAppService_supportedTypes);
+                for (CharSequence cs : types) {
+                    mTypes.add(cs.toString());
+                }
+
+                sa.recycle();
+            } catch (IOException | XmlPullParserException e) {
+                throw new IllegalStateException(
+                        "Failed reading meta-data for " + si.packageName, e);
+            } catch (PackageManager.NameNotFoundException e) {
+                throw new IllegalStateException("No resources found for " + si.packageName, e);
+            }
+        }
+    }
+}
diff --git a/media/java/android/media/tv/interactive/TvIAppManager.java b/media/java/android/media/tv/interactive/TvIAppManager.java
index 16e19e7..7479b2b 100644
--- a/media/java/android/media/tv/interactive/TvIAppManager.java
+++ b/media/java/android/media/tv/interactive/TvIAppManager.java
@@ -20,15 +20,26 @@
 import android.annotation.Nullable;
 import android.annotation.SystemService;
 import android.content.Context;
+import android.media.tv.TvInputManager;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.Pools;
 import android.util.SparseArray;
+import android.view.InputChannel;
+import android.view.InputEvent;
+import android.view.InputEventSender;
 import android.view.Surface;
 
 import com.android.internal.util.Preconditions;
 
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
 /**
  * Central system API to the overall TV interactive application framework (TIAF) architecture, which
  * arbitrates interaction between applications and interactive apps.
@@ -45,10 +56,15 @@
     private final SparseArray<SessionCallbackRecord> mSessionCallbackRecordMap =
             new SparseArray<>();
 
+    // @GuardedBy("mLock")
+    private final List<TvIAppCallbackRecord> mCallbackRecords = new LinkedList<>();
+
     // A sequence number for the next session to be created. Should be protected by a lock
     // {@code mSessionCallbackRecordMap}.
     private int mNextSeq;
 
+    private final Object mLock = new Object();
+
     private final ITvIAppClient mClient;
 
     /** @hide */
@@ -57,8 +73,8 @@
         mUserId = userId;
         mClient = new ITvIAppClient.Stub() {
             @Override
-            public void onSessionCreated(String iAppServiceId, IBinder token, int seq) {
-                // TODO: use InputChannel for input events
+            public void onSessionCreated(String iAppServiceId, IBinder token, InputChannel channel,
+                    int seq) {
                 synchronized (mSessionCallbackRecordMap) {
                     SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
                     if (record == null) {
@@ -67,7 +83,7 @@
                     }
                     Session session = null;
                     if (token != null) {
-                        session = new Session(token, mService, mUserId, seq,
+                        session = new Session(token, channel, mService, mUserId, seq,
                                 mSessionCallbackRecordMap);
                     } else {
                         mSessionCallbackRecordMap.delete(seq);
@@ -102,6 +118,154 @@
                 }
             }
         };
+        ITvIAppManagerCallback managerCallback = new ITvIAppManagerCallback.Stub() {
+            // TODO: handle IApp service state changes
+            @Override
+            public void onIAppServiceAdded(String iAppServiceId) {
+                synchronized (mLock) {
+                    for (TvIAppCallbackRecord record : mCallbackRecords) {
+                        record.postIAppServiceAdded(iAppServiceId);
+                    }
+                }
+            }
+
+            @Override
+            public void onIAppServiceRemoved(String iAppServiceId) {
+                synchronized (mLock) {
+                    for (TvIAppCallbackRecord record : mCallbackRecords) {
+                        record.postIAppServiceRemoved(iAppServiceId);
+                    }
+                }
+            }
+
+            @Override
+            public void onIAppServiceUpdated(String iAppServiceId) {
+                synchronized (mLock) {
+                    for (TvIAppCallbackRecord record : mCallbackRecords) {
+                        record.postIAppServiceUpdated(iAppServiceId);
+                    }
+                }
+            }
+
+            @Override
+            public void onTvIAppInfoUpdated(TvIAppInfo iAppInfo) {
+                // TODO: add public API updateIAppInfo()
+                synchronized (mLock) {
+                    for (TvIAppCallbackRecord record : mCallbackRecords) {
+                        record.postTvIAppInfoUpdated(iAppInfo);
+                    }
+                }
+            }
+        };
+        try {
+            if (mService != null) {
+                mService.registerCallback(managerCallback, mUserId);
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Callback used to monitor status of the TV IApp.
+     * @hide
+     */
+    public abstract static class TvIAppCallback {
+        /**
+         * This is called when a TV IApp service is added to the system.
+         *
+         * <p>Normally it happens when the user installs a new TV IApp service package that
+         * implements {@link TvIAppService} interface.
+         *
+         * @param iAppServiceId The ID of the TV IApp service.
+         */
+        public void onIAppServiceAdded(String iAppServiceId) {
+        }
+
+        /**
+         * This is called when a TV IApp service is removed from the system.
+         *
+         * <p>Normally it happens when the user uninstalls the previously installed TV IApp service
+         * package.
+         *
+         * @param iAppServiceId The ID of the TV IApp service.
+         */
+        public void onIAppServiceRemoved(String iAppServiceId) {
+        }
+
+        /**
+         * This is called when a TV IApp service is updated on the system.
+         *
+         * <p>Normally it happens when a previously installed TV IApp service package is
+         * re-installed or a newer version of the package exists becomes available/unavailable.
+         *
+         * @param iAppServiceId The ID of the TV IApp service.
+         */
+        public void onIAppServiceUpdated(String iAppServiceId) {
+        }
+
+        /**
+         * This is called when the information about an existing TV IApp service has been updated.
+         *
+         * <p>Because the system automatically creates a <code>TvIAppInfo</code> object for each TV
+         * IApp service based on the information collected from the
+         * <code>AndroidManifest.xml</code>, this method is only called back when such information
+         * has changed dynamically.
+         *
+         * @param iAppInfo The <code>TvIAppInfo</code> object that contains new information.
+         */
+        public void onTvIAppInfoUpdated(TvIAppInfo iAppInfo) {
+        }
+    }
+
+    private static final class TvIAppCallbackRecord {
+        private final TvIAppCallback mCallback;
+        private final Handler mHandler;
+
+        TvIAppCallbackRecord(TvIAppCallback callback, Handler handler) {
+            mCallback = callback;
+            mHandler = handler;
+        }
+
+        public TvIAppCallback getCallback() {
+            return mCallback;
+        }
+
+        public void postIAppServiceAdded(final String iAppServiceId) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onIAppServiceAdded(iAppServiceId);
+                }
+            });
+        }
+
+        public void postIAppServiceRemoved(final String iAppServiceId) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onIAppServiceRemoved(iAppServiceId);
+                }
+            });
+        }
+
+        public void postIAppServiceUpdated(final String iAppServiceId) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onIAppServiceUpdated(iAppServiceId);
+                }
+            });
+        }
+
+        public void postTvIAppInfoUpdated(final TvIAppInfo iAppInfo) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mCallback.onTvIAppInfoUpdated(iAppInfo);
+                }
+            });
+        }
     }
 
     /**
@@ -139,26 +303,101 @@
     }
 
     /**
+     * Returns the complete list of TV IApp service on the system.
+     *
+     * @return List of {@link TvIAppInfo} for each TV IApp service that describes its meta
+     *         information.
+     * @hide
+     */
+    public List<TvIAppInfo> getTvIAppServiceList() {
+        try {
+            return mService.getTvIAppServiceList(mUserId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Registers a {@link TvIAppManager.TvIAppCallback}.
+     *
+     * @param callback A callback used to monitor status of the TV IApp services.
+     * @param handler A {@link Handler} that the status change will be delivered to.
+     * @hide
+     */
+    public void registerCallback(@NonNull TvIAppCallback callback, @NonNull Handler handler) {
+        Preconditions.checkNotNull(callback);
+        Preconditions.checkNotNull(handler);
+        synchronized (mLock) {
+            mCallbackRecords.add(new TvIAppCallbackRecord(callback, handler));
+        }
+    }
+
+    /**
+     * Unregisters the existing {@link TvIAppManager.TvIAppCallback}.
+     *
+     * @param callback The existing callback to remove.
+     * @hide
+     */
+    public void unregisterCallback(@NonNull final TvIAppCallback callback) {
+        Preconditions.checkNotNull(callback);
+        synchronized (mLock) {
+            for (Iterator<TvIAppCallbackRecord> it = mCallbackRecords.iterator();
+                    it.hasNext(); ) {
+                TvIAppCallbackRecord record = it.next();
+                if (record.getCallback() == callback) {
+                    it.remove();
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
      * The Session provides the per-session functionality of interactive app.
      * @hide
      */
     public static final class Session {
+        static final int DISPATCH_IN_PROGRESS = -1;
+        static final int DISPATCH_NOT_HANDLED = 0;
+        static final int DISPATCH_HANDLED = 1;
+
+        private static final long INPUT_SESSION_NOT_RESPONDING_TIMEOUT = 2500;
+
         private final ITvIAppManager mService;
         private final int mUserId;
         private final int mSeq;
         private final SparseArray<SessionCallbackRecord> mSessionCallbackRecordMap;
 
-        private IBinder mToken;
+        // For scheduling input event handling on the main thread. This also serves as a lock to
+        // protect pending input events and the input channel.
+        private final InputEventHandler mHandler = new InputEventHandler(Looper.getMainLooper());
 
-        private Session(IBinder token, ITvIAppManager service, int userId, int seq,
-                SparseArray<SessionCallbackRecord> sessionCallbackRecordMap) {
+        private TvInputManager.Session mInputSession;
+        private final Pools.Pool<PendingEvent> mPendingEventPool = new Pools.SimplePool<>(20);
+        private final SparseArray<PendingEvent> mPendingEvents = new SparseArray<>(20);
+
+        private IBinder mToken;
+        private TvInputEventSender mSender;
+        private InputChannel mInputChannel;
+
+        private Session(IBinder token, InputChannel channel, ITvIAppManager service, int userId,
+                int seq, SparseArray<SessionCallbackRecord> sessionCallbackRecordMap) {
             mToken = token;
+            mInputChannel = channel;
             mService = service;
             mUserId = userId;
             mSeq = seq;
             mSessionCallbackRecordMap = sessionCallbackRecordMap;
         }
 
+        public TvInputManager.Session getInputSession() {
+            return mInputSession;
+        }
+
+        public void setInputSession(TvInputManager.Session inputSession) {
+            mInputSession = inputSession;
+        }
+
         void startIApp() {
             if (mToken == null) {
                 Log.w(TAG, "The session has been already released");
@@ -210,6 +449,43 @@
         }
 
         /**
+         * Dispatches an input event to this session.
+         *
+         * @param event An {@link InputEvent} to dispatch. Cannot be {@code null}.
+         * @param token A token used to identify the input event later in the callback.
+         * @param callback A callback used to receive the dispatch result. Cannot be {@code null}.
+         * @param handler A {@link Handler} that the dispatch result will be delivered to. Cannot be
+         *            {@code null}.
+         * @return Returns {@link #DISPATCH_HANDLED} if the event was handled. Returns
+         *         {@link #DISPATCH_NOT_HANDLED} if the event was not handled. Returns
+         *         {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the callback will
+         *         be invoked later.
+         * @hide
+         */
+        public int dispatchInputEvent(@NonNull InputEvent event, Object token,
+                @NonNull FinishedInputEventCallback callback, @NonNull Handler handler) {
+            Preconditions.checkNotNull(event);
+            Preconditions.checkNotNull(callback);
+            Preconditions.checkNotNull(handler);
+            synchronized (mHandler) {
+                if (mInputChannel == null) {
+                    return DISPATCH_NOT_HANDLED;
+                }
+                PendingEvent p = obtainPendingEventLocked(event, token, callback, handler);
+                if (Looper.myLooper() == Looper.getMainLooper()) {
+                    // Already running on the main thread so we can send the event immediately.
+                    return sendInputEventOnMainLooperLocked(p);
+                }
+
+                // Post the event to the main thread.
+                Message msg = mHandler.obtainMessage(InputEventHandler.MSG_SEND_INPUT_EVENT, p);
+                msg.setAsynchronous(true);
+                mHandler.sendMessage(msg);
+                return DISPATCH_IN_PROGRESS;
+            }
+        }
+
+        /**
          * Releases this session.
          */
         public void release() {
@@ -226,12 +502,208 @@
             releaseInternal();
         }
 
+        private void flushPendingEventsLocked() {
+            mHandler.removeMessages(InputEventHandler.MSG_FLUSH_INPUT_EVENT);
+
+            final int count = mPendingEvents.size();
+            for (int i = 0; i < count; i++) {
+                int seq = mPendingEvents.keyAt(i);
+                Message msg = mHandler.obtainMessage(
+                        InputEventHandler.MSG_FLUSH_INPUT_EVENT, seq, 0);
+                msg.setAsynchronous(true);
+                msg.sendToTarget();
+            }
+        }
+
         private void releaseInternal() {
             mToken = null;
+            synchronized (mHandler) {
+                if (mInputChannel != null) {
+                    if (mSender != null) {
+                        flushPendingEventsLocked();
+                        mSender.dispose();
+                        mSender = null;
+                    }
+                    mInputChannel.dispose();
+                    mInputChannel = null;
+                }
+            }
             synchronized (mSessionCallbackRecordMap) {
                 mSessionCallbackRecordMap.delete(mSeq);
             }
         }
+
+        private PendingEvent obtainPendingEventLocked(InputEvent event, Object token,
+                FinishedInputEventCallback callback, Handler handler) {
+            PendingEvent p = mPendingEventPool.acquire();
+            if (p == null) {
+                p = new PendingEvent();
+            }
+            p.mEvent = event;
+            p.mEventToken = token;
+            p.mCallback = callback;
+            p.mEventHandler = handler;
+            return p;
+        }
+
+        // Assumes the event has already been removed from the queue.
+        void invokeFinishedInputEventCallback(PendingEvent p, boolean handled) {
+            p.mHandled = handled;
+            if (p.mEventHandler.getLooper().isCurrentThread()) {
+                // Already running on the callback handler thread so we can send the callback
+                // immediately.
+                p.run();
+            } else {
+                // Post the event to the callback handler thread.
+                // In this case, the callback will be responsible for recycling the event.
+                Message msg = Message.obtain(p.mEventHandler, p);
+                msg.setAsynchronous(true);
+                msg.sendToTarget();
+            }
+        }
+
+        // Must be called on the main looper
+        private void sendInputEventAndReportResultOnMainLooper(PendingEvent p) {
+            synchronized (mHandler) {
+                int result = sendInputEventOnMainLooperLocked(p);
+                if (result == DISPATCH_IN_PROGRESS) {
+                    return;
+                }
+            }
+
+            invokeFinishedInputEventCallback(p, false);
+        }
+
+        private int sendInputEventOnMainLooperLocked(PendingEvent p) {
+            if (mInputChannel != null) {
+                if (mSender == null) {
+                    mSender = new TvInputEventSender(mInputChannel, mHandler.getLooper());
+                }
+
+                final InputEvent event = p.mEvent;
+                final int seq = event.getSequenceNumber();
+                if (mSender.sendInputEvent(seq, event)) {
+                    mPendingEvents.put(seq, p);
+                    Message msg = mHandler.obtainMessage(
+                            InputEventHandler.MSG_TIMEOUT_INPUT_EVENT, p);
+                    msg.setAsynchronous(true);
+                    mHandler.sendMessageDelayed(msg, INPUT_SESSION_NOT_RESPONDING_TIMEOUT);
+                    return DISPATCH_IN_PROGRESS;
+                }
+
+                Log.w(TAG, "Unable to send input event to session: " + mToken + " dropping:"
+                        + event);
+            }
+            return DISPATCH_NOT_HANDLED;
+        }
+
+        void finishedInputEvent(int seq, boolean handled, boolean timeout) {
+            final PendingEvent p;
+            synchronized (mHandler) {
+                int index = mPendingEvents.indexOfKey(seq);
+                if (index < 0) {
+                    return; // spurious, event already finished or timed out
+                }
+
+                p = mPendingEvents.valueAt(index);
+                mPendingEvents.removeAt(index);
+
+                if (timeout) {
+                    Log.w(TAG, "Timeout waiting for session to handle input event after "
+                            + INPUT_SESSION_NOT_RESPONDING_TIMEOUT + " ms: " + mToken);
+                } else {
+                    mHandler.removeMessages(InputEventHandler.MSG_TIMEOUT_INPUT_EVENT, p);
+                }
+            }
+
+            invokeFinishedInputEventCallback(p, handled);
+        }
+
+        private void recyclePendingEventLocked(PendingEvent p) {
+            p.recycle();
+            mPendingEventPool.release(p);
+        }
+
+        /**
+         * Callback that is invoked when an input event that was dispatched to this session has been
+         * finished.
+         *
+         * @hide
+         */
+        public interface FinishedInputEventCallback {
+            /**
+             * Called when the dispatched input event is finished.
+             *
+             * @param token A token passed to {@link #dispatchInputEvent}.
+             * @param handled {@code true} if the dispatched input event was handled properly.
+             *            {@code false} otherwise.
+             */
+            void onFinishedInputEvent(Object token, boolean handled);
+        }
+
+        private final class InputEventHandler extends Handler {
+            public static final int MSG_SEND_INPUT_EVENT = 1;
+            public static final int MSG_TIMEOUT_INPUT_EVENT = 2;
+            public static final int MSG_FLUSH_INPUT_EVENT = 3;
+
+            InputEventHandler(Looper looper) {
+                super(looper, null, true);
+            }
+
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case MSG_SEND_INPUT_EVENT: {
+                        sendInputEventAndReportResultOnMainLooper((PendingEvent) msg.obj);
+                        return;
+                    }
+                    case MSG_TIMEOUT_INPUT_EVENT: {
+                        finishedInputEvent(msg.arg1, false, true);
+                        return;
+                    }
+                    case MSG_FLUSH_INPUT_EVENT: {
+                        finishedInputEvent(msg.arg1, false, false);
+                        return;
+                    }
+                }
+            }
+        }
+
+        private final class TvInputEventSender extends InputEventSender {
+            TvInputEventSender(InputChannel inputChannel, Looper looper) {
+                super(inputChannel, looper);
+            }
+
+            @Override
+            public void onInputEventFinished(int seq, boolean handled) {
+                finishedInputEvent(seq, handled, false);
+            }
+        }
+
+        private final class PendingEvent implements Runnable {
+            public InputEvent mEvent;
+            public Object mEventToken;
+            public FinishedInputEventCallback mCallback;
+            public Handler mEventHandler;
+            public boolean mHandled;
+
+            public void recycle() {
+                mEvent = null;
+                mEventToken = null;
+                mCallback = null;
+                mEventHandler = null;
+                mHandled = false;
+            }
+
+            @Override
+            public void run() {
+                mCallback.onFinishedInputEvent(mEventToken, mHandled);
+
+                synchronized (mEventHandler) {
+                    recyclePendingEventLocked(this);
+                }
+            }
+        }
     }
 
     private static final class SessionCallbackRecord {
diff --git a/media/java/android/media/tv/interactive/TvIAppService.java b/media/java/android/media/tv/interactive/TvIAppService.java
index b385d9c..25dec62 100644
--- a/media/java/android/media/tv/interactive/TvIAppService.java
+++ b/media/java/android/media/tv/interactive/TvIAppService.java
@@ -25,10 +25,17 @@
 import android.content.Intent;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.InputChannel;
+import android.view.InputDevice;
+import android.view.InputEvent;
+import android.view.InputEventReceiver;
 import android.view.KeyEvent;
+import android.view.MotionEvent;
 import android.view.Surface;
 
 import com.android.internal.os.SomeArgs;
@@ -38,35 +45,62 @@
 
 /**
  * The TvIAppService class represents a TV interactive applications RTE.
- * @hide
  */
 public abstract class TvIAppService extends Service {
     private static final boolean DEBUG = false;
     private static final String TAG = "TvIAppService";
 
-    private final Handler mServiceHandler = new ServiceHandler();
+    // TODO: cleanup and unhide APIs.
 
     /**
-     * This is the interface name that a service implementing an environment to run Tv IApp should
-     * say that it support -- that is, this is the action it uses for its intent filter. To be
-     * supported, the service must also require the BIND_TV_IAPP permission so that other
-     * applications cannot abuse it.
+     * This is the interface name that a service implementing a TV IApp service should say that it
+     * supports -- that is, this is the action it uses for its intent filter. To be supported, the
+     * service must also require the android.Manifest.permission#BIND_TV_IAPP permission so
+     * that other applications cannot abuse it.
      */
-    public static final String SERVICE_INTERFACE = "android.media.tv.TvIAppService";
+    public static final String SERVICE_INTERFACE = "android.media.tv.interactive.TvIAppService";
 
+    /**
+     * Name under which a TvIAppService component publishes information about itself. This meta-data
+     * must reference an XML resource containing an
+     * <code>&lt;{@link android.R.styleable#TvIAppService tv-iapp}&gt;</code>
+     * tag.
+     */
+    public static final String SERVICE_META_DATA = "android.media.tv.interactive.app";
+
+    private final Handler mServiceHandler = new ServiceHandler();
+    private final RemoteCallbackList<ITvIAppServiceCallback> mCallbacks =
+            new RemoteCallbackList<>();
+
+    /** @hide */
     @Override
     public final IBinder onBind(Intent intent) {
         ITvIAppService.Stub tvIAppServiceBinder = new ITvIAppService.Stub() {
+            @Override
+            public void registerCallback(ITvIAppServiceCallback cb) {
+                if (cb != null) {
+                    mCallbacks.register(cb);
+                }
+            }
 
             @Override
-            public void createSession(ITvIAppSessionCallback cb, String iAppServiceId, int type) {
+            public void unregisterCallback(ITvIAppServiceCallback cb) {
+                if (cb != null) {
+                    mCallbacks.unregister(cb);
+                }
+            }
+
+            @Override
+            public void createSession(InputChannel channel, ITvIAppSessionCallback cb,
+                    String iAppServiceId, int type) {
                 if (cb == null) {
                     return;
                 }
                 SomeArgs args = SomeArgs.obtain();
-                args.arg1 = cb;
-                args.arg2 = iAppServiceId;
-                args.arg3 = type;
+                args.arg1 = channel;
+                args.arg2 = cb;
+                args.arg3 = iAppServiceId;
+                args.arg4 = type;
                 mServiceHandler.obtainMessage(ServiceHandler.DO_CREATE_SESSION, args)
                         .sendToTarget();
             }
@@ -83,14 +117,21 @@
      *
      * @param iAppServiceId The ID of the TV IApp associated with the session.
      * @param type The type of the TV IApp associated with the session.
+     * @hide
      */
     @Nullable
-    public abstract Session onCreateSession(@NonNull String iAppServiceId, int type);
+    public Session onCreateSession(@NonNull String iAppServiceId, int type) {
+        // TODO: make it abstract when unhide
+        return null;
+    }
 
     /**
      * Base class for derived classes to implement to provide a TV interactive app session.
+     * @hide
      */
     public abstract static class Session implements KeyEvent.Callback {
+        private final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState();
+
         private final Object mLock = new Object();
         // @GuardedBy("mLock")
         private ITvIAppSessionCallback mSessionCallback;
@@ -113,6 +154,7 @@
 
         /**
          * Starts TvIAppService session.
+         * @hide
          */
         public void onStartIApp() {
         }
@@ -121,7 +163,7 @@
          * Called when the application sets the surface.
          *
          * <p>The TV IApp service should render interactive app UI onto the given surface. When
-         * called with {@code null}, the input service should immediately free any references to the
+         * called with {@code null}, the IApp service should immediately free any references to the
          * currently set surface and stop using it.
          *
          * @param surface The surface to be used for interactive app UI rendering. Can be
@@ -144,11 +186,66 @@
 
         /**
          * Releases TvIAppService session.
+         * @hide
          */
         public void onRelease() {
         }
 
         /**
+         * TODO: JavaDoc of APIs related to input events.
+         * @hide
+         */
+        @Override
+        public boolean onKeyDown(int keyCode, KeyEvent event) {
+            return false;
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+            return false;
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
+            return false;
+        }
+
+        /**
+         * @hide
+         */
+        @Override
+        public boolean onKeyUp(int keyCode, KeyEvent event) {
+            return false;
+        }
+
+        /**
+         * @hide
+         */
+        public boolean onTouchEvent(MotionEvent event) {
+            return false;
+        }
+
+        /**
+         * @hide
+         */
+        public boolean onTrackballEvent(MotionEvent event) {
+            return false;
+        }
+
+        /**
+         * @hide
+         */
+        public boolean onGenericMotionEvent(MotionEvent event) {
+            return false;
+        }
+
+        /**
          * Assigns a size and position to the surface passed in {@link #onSetSurface}. The position
          * is relative to the overlay view that sits on top of this surface.
          *
@@ -193,6 +290,39 @@
             }
         }
 
+        /**
+         * Takes care of dispatching incoming input events and tells whether the event was handled.
+         */
+        int dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
+            if (DEBUG) Log.d(TAG, "dispatchInputEvent(" + event + ")");
+            if (event instanceof KeyEvent) {
+                KeyEvent keyEvent = (KeyEvent) event;
+                if (keyEvent.dispatch(this, mDispatcherState, this)) {
+                    return TvIAppManager.Session.DISPATCH_HANDLED;
+                }
+
+                // TODO: special handlings of navigation keys and media keys
+            } else if (event instanceof MotionEvent) {
+                MotionEvent motionEvent = (MotionEvent) event;
+                final int source = motionEvent.getSource();
+                if (motionEvent.isTouchEvent()) {
+                    if (onTouchEvent(motionEvent)) {
+                        return TvIAppManager.Session.DISPATCH_HANDLED;
+                    }
+                } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
+                    if (onTrackballEvent(motionEvent)) {
+                        return TvIAppManager.Session.DISPATCH_HANDLED;
+                    }
+                } else {
+                    if (onGenericMotionEvent(motionEvent)) {
+                        return TvIAppManager.Session.DISPATCH_HANDLED;
+                    }
+                }
+            }
+            // TODO: handle overlay view
+            return TvIAppManager.Session.DISPATCH_NOT_HANDLED;
+        }
+
         private void initialize(ITvIAppSessionCallback callback) {
             synchronized (mLock) {
                 mSessionCallback = callback;
@@ -245,12 +375,20 @@
 
     /**
      * Implements the internal ITvIAppSession interface.
+     * @hide
      */
     public static class ITvIAppSessionWrapper extends ITvIAppSession.Stub {
+        // TODO: put ITvIAppSessionWrapper in a separate Java file
         private final Session mSessionImpl;
+        private InputChannel mChannel;
+        private TvIAppEventReceiver mReceiver;
 
-        public ITvIAppSessionWrapper(Session mSessionImpl) {
+        public ITvIAppSessionWrapper(Context context, Session mSessionImpl, InputChannel channel) {
             this.mSessionImpl = mSessionImpl;
+            mChannel = channel;
+            if (channel != null) {
+                mReceiver = new TvIAppEventReceiver(channel, context.getMainLooper());
+            }
         }
 
         @Override
@@ -272,6 +410,26 @@
         public void dispatchSurfaceChanged(int format, int width, int height) {
             mSessionImpl.dispatchSurfaceChanged(format, width, height);
         }
+
+        private final class TvIAppEventReceiver extends InputEventReceiver {
+            TvIAppEventReceiver(InputChannel inputChannel, Looper looper) {
+                super(inputChannel, looper);
+            }
+
+            @Override
+            public void onInputEvent(InputEvent event) {
+                if (mSessionImpl == null) {
+                    // The session has been finished.
+                    finishInputEvent(event, false);
+                    return;
+                }
+
+                int handled = mSessionImpl.dispatchInputEvent(event, this);
+                if (handled != TvIAppManager.Session.DISPATCH_IN_PROGRESS) {
+                    finishInputEvent(event, handled == TvIAppManager.Session.DISPATCH_HANDLED);
+                }
+            }
+        }
     }
 
     @SuppressLint("HandlerLeak")
@@ -284,9 +442,10 @@
             switch (msg.what) {
                 case DO_CREATE_SESSION: {
                     SomeArgs args = (SomeArgs) msg.obj;
-                    ITvIAppSessionCallback cb = (ITvIAppSessionCallback) args.arg1;
-                    String iAppServiceId = (String) args.arg2;
-                    int type = (int) args.arg3;
+                    InputChannel channel = (InputChannel) args.arg1;
+                    ITvIAppSessionCallback cb = (ITvIAppSessionCallback) args.arg2;
+                    String iAppServiceId = (String) args.arg3;
+                    int type = (int) args.arg4;
                     args.recycle();
                     Session sessionImpl = onCreateSession(iAppServiceId, type);
                     if (sessionImpl == null) {
@@ -298,7 +457,8 @@
                         }
                         return;
                     }
-                    ITvIAppSession stub = new ITvIAppSessionWrapper(sessionImpl);
+                    ITvIAppSession stub = new ITvIAppSessionWrapper(
+                            TvIAppService.this, sessionImpl, channel);
 
                     SomeArgs someArgs = SomeArgs.obtain();
                     someArgs.arg1 = sessionImpl;
diff --git a/media/java/android/media/tv/interactive/TvIAppView.java b/media/java/android/media/tv/interactive/TvIAppView.java
index adaaab0..1b25c23 100644
--- a/media/java/android/media/tv/interactive/TvIAppView.java
+++ b/media/java/android/media/tv/interactive/TvIAppView.java
@@ -16,9 +16,12 @@
 
 package android.media.tv.interactive;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
+import android.media.tv.TvInputManager;
+import android.media.tv.TvView;
 import android.media.tv.interactive.TvIAppManager.Session;
 import android.media.tv.interactive.TvIAppManager.SessionCallback;
 import android.os.Handler;
@@ -39,6 +42,11 @@
     private static final String TAG = "TvIAppView";
     private static final boolean DEBUG = false;
 
+    private static final int SET_TVVIEW_SUCCESS = 1;
+    private static final int SET_TVVIEW_FAIL = 2;
+    private static final int UNSET_TVVIEW_SUCCESS = 3;
+    private static final int UNSET_TVVIEW_FAIL = 4;
+
     private final TvIAppManager mTvIAppManager;
     private final Handler mHandler = new Handler();
     private Session mSession;
@@ -213,6 +221,39 @@
         }
     }
 
+    public Session getIAppSession() {
+        return mSession;
+    }
+
+    /**
+     * Sets the TvIAppView to receive events from TIS. This method links the session of
+     * TvIAppManager to TvInputManager session, so the TIAS can get the TIS events.
+     *
+     * @param tvView the TvView to be linked to this TvIAppView via linking of Sessions.
+     * @return to be added
+     */
+    public int setTvView(@Nullable TvView tvView) {
+        if (tvView == null) {
+            return unsetTvView();
+        }
+        TvInputManager.Session inputSession = tvView.getInputSession();
+        if (inputSession == null || mSession == null) {
+            return SET_TVVIEW_FAIL;
+        }
+        mSession.setInputSession(inputSession);
+        inputSession.setIAppSession(mSession);
+        return SET_TVVIEW_SUCCESS;
+    }
+
+    private int unsetTvView() {
+        if (mSession == null || mSession.getInputSession() == null) {
+            return UNSET_TVVIEW_FAIL;
+        }
+        mSession.getInputSession().setIAppSession(null);
+        mSession.setInputSession(null);
+        return UNSET_TVVIEW_SUCCESS;
+    }
+
     private class MySessionCallback extends SessionCallback {
         final String mIAppServiceId;
         int mType;
diff --git a/media/java/android/media/tv/tuner/filter/AvSettings.java b/media/java/android/media/tv/tuner/filter/AvSettings.java
index 8bcf3d2..ed04754 100644
--- a/media/java/android/media/tv/tuner/filter/AvSettings.java
+++ b/media/java/android/media/tv/tuner/filter/AvSettings.java
@@ -186,9 +186,10 @@
     private final boolean mIsPassthrough;
     private int mAudioStreamType = AUDIO_STREAM_TYPE_UNDEFINED;
     private int mVideoStreamType = VIDEO_STREAM_TYPE_UNDEFINED;
+    private final boolean mUseSecureMemory;
 
-    private AvSettings(int mainType, boolean isAudio, boolean isPassthrough,
-            int audioStreamType, int videoStreamType) {
+    private AvSettings(int mainType, boolean isAudio, boolean isPassthrough, int audioStreamType,
+            int videoStreamType, boolean useSecureMemory) {
         super(TunerUtils.getFilterSubtype(
                 mainType,
                 isAudio
@@ -197,6 +198,7 @@
         mIsPassthrough = isPassthrough;
         mAudioStreamType = audioStreamType;
         mVideoStreamType = videoStreamType;
+        mUseSecureMemory = useSecureMemory;
     }
 
     /**
@@ -223,6 +225,16 @@
     }
 
     /**
+     * Checks whether secure memory is used.
+     *
+     * <p>This query is only supported by Tuner HAL 2.0 or higher. The return value on HAL 1.1 and
+     * lower is undefined. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
+     */
+    public boolean useSecureMemory() {
+        return mUseSecureMemory;
+    }
+
+    /**
      * Creates a builder for {@link AvSettings}.
      *
      * @param mainType the filter main type.
@@ -239,9 +251,10 @@
     public static class Builder {
         private final int mMainType;
         private final boolean mIsAudio;
-        private boolean mIsPassthrough;
+        private boolean mIsPassthrough = false;
         private int mAudioStreamType = AUDIO_STREAM_TYPE_UNDEFINED;
         private int mVideoStreamType = VIDEO_STREAM_TYPE_UNDEFINED;
+        boolean mUseSecureMemory = false;
 
         private Builder(int mainType, boolean isAudio) {
             mMainType = mainType;
@@ -250,6 +263,8 @@
 
         /**
          * Sets whether it's passthrough.
+         *
+         * <p>Default value is {@code false}.
          */
         @NonNull
         public Builder setPassthrough(boolean isPassthrough) {
@@ -263,6 +278,8 @@
          * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
          * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
          *
+         * <p>Default is {@link #AUDIO_STREAM_TYPE_UNDEFINED}.
+         *
          * @param audioStreamType the audio stream type to set.
          */
         @NonNull
@@ -281,6 +298,8 @@
          * <p>This API is only supported by Tuner HAL 1.1 or higher. Unsupported version would cause
          * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
          *
+         * <p>Default value is {@link #VIDEO_STREAM_TYPE_UNDEFINED}.
+         *
          * @param videoStreamType the video stream type to set.
          */
         @NonNull
@@ -294,12 +313,29 @@
         }
 
         /**
+         * Sets whether secure memory should be used.
+         *
+         * <p>This API is only supported by Tuner HAL 2.0 or higher. Unsupported version would cause
+         * no-op. Use {@link TunerVersionChecker#getTunerVersion()} to check the version.
+         *
+         * <p>Default value is {@code false}.
+         */
+        @NonNull
+        public Builder setUseSecureMemory(boolean useSecureMemory) {
+            if (TunerVersionChecker.checkHigherOrEqualVersionTo(
+                        TunerVersionChecker.TUNER_VERSION_2_0, "setSecureMemory")) {
+                mUseSecureMemory = useSecureMemory;
+            }
+            return this;
+        }
+
+        /**
          * Builds a {@link AvSettings} object.
          */
         @NonNull
         public AvSettings build() {
-            return new AvSettings(mMainType, mIsAudio, mIsPassthrough,
-                    mAudioStreamType, mVideoStreamType);
+            return new AvSettings(mMainType, mIsAudio, mIsPassthrough, mAudioStreamType,
+                    mVideoStreamType, mUseSecureMemory);
         }
     }
 }
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index ae271120..f0f576e 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -251,8 +251,8 @@
     private native int nativeFlushFilter();
     private native int nativeRead(byte[] buffer, long offset, long size);
     private native int nativeClose();
-    private native String nativeCreateSharedFilter();
-    private native void nativeReleaseSharedFilter(String token);
+    private native String nativeAcquireSharedFilterToken();
+    private native void nativeFreeSharedFilterToken(String token);
 
     // Called by JNI
     private Filter(long id) {
@@ -562,20 +562,20 @@
     }
 
     /**
-     * Creates a shared filter.
+     * Acquires a shared filter token.
      *
      * @return a string shared filter token.
      */
     @Nullable
-    public String createSharedFilter() {
+    public String acquireSharedFilterToken() {
         synchronized (mLock) {
             TunerUtils.checkResourceState(TAG, mIsClosed);
             if (mIsStarted || mIsShared) {
-                Log.d(TAG, "Create shared filter in a wrong state, started: " +
+                Log.d(TAG, "Acquire shared filter in a wrong state, started: " +
                      mIsStarted + "shared: " + mIsShared);
                 return null;
             }
-            String token = nativeCreateSharedFilter();
+            String token = nativeAcquireSharedFilterToken();
             if (token != null) {
                 mIsShared = true;
             }
@@ -584,17 +584,17 @@
     }
 
     /**
-     * Releases a shared filter.
+     * Frees a shared filter token.
      *
      * @param filterToken the token of the shared filter being released.
      */
-    public void releaseSharedFilter(@NonNull String filterToken) {
+    public void freeSharedFilterToken(@NonNull String filterToken) {
         synchronized (mLock) {
             TunerUtils.checkResourceState(TAG, mIsClosed);
             if (!mIsShared) {
                 return;
             }
-            nativeReleaseSharedFilter(filterToken);
+            nativeFreeSharedFilterToken(filterToken);
             mIsShared = false;
         }
     }
diff --git a/media/java/android/media/tv/tuner/filter/RecordSettings.java b/media/java/android/media/tv/tuner/filter/RecordSettings.java
index cd70365..d34581d 100644
--- a/media/java/android/media/tv/tuner/filter/RecordSettings.java
+++ b/media/java/android/media/tv/tuner/filter/RecordSettings.java
@@ -20,11 +20,11 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.hardware.tv.tuner.DemuxRecordScIndexType;
+import android.hardware.tv.tuner.DemuxScAvcIndex;
 import android.hardware.tv.tuner.DemuxScHevcIndex;
 import android.hardware.tv.tuner.DemuxScIndex;
 import android.hardware.tv.tuner.DemuxTsIndex;
 import android.media.tv.tuner.TunerUtils;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -139,7 +139,7 @@
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = "INDEX_TYPE_", value =
-            {INDEX_TYPE_NONE, INDEX_TYPE_SC, INDEX_TYPE_SC_HEVC})
+            {INDEX_TYPE_NONE, INDEX_TYPE_SC, INDEX_TYPE_SC_HEVC, INDEX_TYPE_SC_AVC})
     public @interface ScIndexType {}
 
     /**
@@ -154,6 +154,10 @@
      * Start Code index for HEVC.
      */
     public static final int INDEX_TYPE_SC_HEVC = DemuxRecordScIndexType.SC_HEVC;
+    /**
+     * Start Code index for AVC.
+     */
+    public static final int INDEX_TYPE_SC_AVC = DemuxRecordScIndexType.SC_AVC;
 
     /**
      * Indexes can be tagged by Start Code in PES (Packetized Elementary Stream)
@@ -187,23 +191,23 @@
     /**
      * All blocks are coded as I blocks.
      */
-    public static final int SC_INDEX_I_SLICE = DemuxScIndex.I_SLICE;
+    public static final int SC_INDEX_I_SLICE = DemuxScAvcIndex.I_SLICE << 4;
     /**
      * Blocks are coded as I or P blocks.
      */
-    public static final int SC_INDEX_P_SLICE = DemuxScIndex.P_SLICE;
+    public static final int SC_INDEX_P_SLICE = DemuxScAvcIndex.P_SLICE << 4;
     /**
      * Blocks are coded as I, P or B blocks.
      */
-    public static final int SC_INDEX_B_SLICE = DemuxScIndex.B_SLICE;
+    public static final int SC_INDEX_B_SLICE = DemuxScAvcIndex.B_SLICE << 4;
     /**
      * A so-called switching I slice that is coded.
      */
-    public static final int SC_INDEX_SI_SLICE = DemuxScIndex.SI_SLICE;
+    public static final int SC_INDEX_SI_SLICE = DemuxScAvcIndex.SI_SLICE << 4;
     /**
      * A so-called switching P slice that is coded.
      */
-    public static final int SC_INDEX_SP_SLICE = DemuxScIndex.SP_SLICE;
+    public static final int SC_INDEX_SP_SLICE = DemuxScAvcIndex.SP_SLICE << 4;
 
     /**
      * Indexes can be tagged by NAL unit group in HEVC according to ISO/IEC 23008-2.
diff --git a/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java b/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java
index fc6451f..ff8f796 100644
--- a/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java
+++ b/media/java/android/media/tv/tuner/filter/SectionSettingsWithTableInfo.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.hardware.tv.tuner.Constant;
 
 /**
  * Table information for Section Filter.
@@ -26,6 +27,12 @@
  */
 @SystemApi
 public class SectionSettingsWithTableInfo extends SectionSettings {
+    /**
+     * The invalid version number of {@link SectionSettingsWithTableInfo}. Tuner HAL will ignore the
+     * {@link SectionSettingsWithTableInfo} version number if this invalid version is set.
+     */
+    public static final int INVALID_TABLE_INFO_VERSION = Constant.INVALID_TABINFO_VERSION;
+
     private final int mTableId;
     private final int mVersion;
 
@@ -64,7 +71,7 @@
      */
     public static class Builder extends SectionSettings.Builder<Builder> {
         private int mTableId;
-        private int mVersion;
+        private int mVersion = INVALID_TABLE_INFO_VERSION;
 
         private Builder(int mainType) {
             super(mainType);
diff --git a/media/java/android/media/tv/tuner/filter/SharedFilter.java b/media/java/android/media/tv/tuner/filter/SharedFilter.java
index f86ad11..056c5d5 100644
--- a/media/java/android/media/tv/tuner/filter/SharedFilter.java
+++ b/media/java/android/media/tv/tuner/filter/SharedFilter.java
@@ -145,7 +145,7 @@
     }
 
     /**
-     * Flushes the filter.
+     * Flushes the shared filter.
      *
      * <p>The data which is already produced by filter but not consumed yet will
      * be cleared.
@@ -162,7 +162,7 @@
     }
 
     /**
-     * Copies filtered data from filter output to the given byte array.
+     * Copies filtered data from shared filter output to the given byte array.
      *
      * @param buffer the buffer to store the filtered data.
      * @param offset the index of the first byte in {@code buffer} to write.
@@ -179,7 +179,7 @@
     }
 
     /**
-     * Stops filtering data and releases the Filter instance.
+     * Stops filtering data and releases the shared filter instance.
      */
     @Override
     public void close() {
diff --git a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
index 1090f33..403bfa7 100644
--- a/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
+++ b/media/java/android/media/tv/tuner/frontend/IsdbtFrontendSettings.java
@@ -581,7 +581,7 @@
          * Gets Number of Segment.
          */
         @IntRange(from = 0, to = 0xff)
-        public int getNumOfSegment() {
+        public int getNumberOfSegment() {
             return mNumOfSegment;
         }
 
@@ -639,7 +639,7 @@
              */
             @NonNull
             @IntRange(from = 0, to = 0xff)
-            public Builder setNumOfSegment(int numOfSegment) {
+            public Builder setNumberOfSegment(int numOfSegment) {
                 mNumOfSegment = numOfSegment;
                 return this;
             }
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index ecd9cc1..39b560b 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -65,6 +65,7 @@
         case HAL_PIXEL_FORMAT_Y8:
         case HAL_PIXEL_FORMAT_Y16:
         case HAL_PIXEL_FORMAT_RAW16:
+        case HAL_PIXEL_FORMAT_RAW12:
         case HAL_PIXEL_FORMAT_RAW10:
         case HAL_PIXEL_FORMAT_RAW_OPAQUE:
         case HAL_PIXEL_FORMAT_BLOB:
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index 24eea30..4c1ed45 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -693,6 +693,10 @@
         sc = tsRecordEvent.scIndexMask.get<DemuxFilterScIndexMask::Tag::scIndex>();
     } else if (tsRecordEvent.scIndexMask.getTag() == DemuxFilterScIndexMask::Tag::scHevc) {
         sc = tsRecordEvent.scIndexMask.get<DemuxFilterScIndexMask::Tag::scHevc>();
+    } else if (tsRecordEvent.scIndexMask.getTag() == DemuxFilterScIndexMask::Tag::scAvc) {
+        sc = tsRecordEvent.scIndexMask.get<DemuxFilterScIndexMask::Tag::scAvc>();
+        // Java uses the values defined by HIDL HAL. Left shift 4 bits.
+        sc = sc << 4;
     }
 
     jint ts = tsRecordEvent.tsIndexMask;
@@ -3391,8 +3395,11 @@
     jclass clazz = env->FindClass("android/media/tv/tuner/filter/AvSettings");
     bool isPassthrough =
             env->GetBooleanField(settings, env->GetFieldID(clazz, "mIsPassthrough", "Z"));
-    DemuxFilterAvSettings filterAvSettings {
-        .isPassthrough = isPassthrough,
+    bool isSecureMemory =
+            env->GetBooleanField(settings, env->GetFieldID(clazz, "mUseSecureMemory", "Z"));
+    DemuxFilterAvSettings filterAvSettings{
+            .isPassthrough = isPassthrough,
+            .isSecureMemory = isSecureMemory,
     };
     return filterAvSettings;
 }
@@ -3440,6 +3447,11 @@
             env->GetIntField(settings, env->GetFieldID(clazz, "mScIndexType", "I")));
     jint scIndexMask = env->GetIntField(settings, env->GetFieldID(clazz, "mScIndexMask", "I"));
 
+    // Backward compatibility for S- apps.
+    if (scIndexType == DemuxRecordScIndexType::SC &&
+        scIndexMask > static_cast<int32_t>(DemuxScIndex::SEQUENCE)) {
+        scIndexType = DemuxRecordScIndexType::SC_AVC;
+    }
     DemuxFilterRecordSettings filterRecordSettings {
         .tsIndexMask = tsIndexMask,
         .scIndexType = scIndexType,
@@ -3448,6 +3460,9 @@
         filterRecordSettings.scIndexMask.set<DemuxFilterScIndexMask::Tag::scIndex>(scIndexMask);
     } else if (scIndexType == DemuxRecordScIndexType::SC_HEVC) {
         filterRecordSettings.scIndexMask.set<DemuxFilterScIndexMask::Tag::scHevc>(scIndexMask);
+    } else if (scIndexType == DemuxRecordScIndexType::SC_AVC) {
+        // Java uses the values defined by HIDL HAL. Right shift 4 bits.
+        filterRecordSettings.scIndexMask.set<DemuxFilterScIndexMask::Tag::scAvc>(scIndexMask >> 4);
     }
     return filterRecordSettings;
 }
@@ -3881,8 +3896,8 @@
 
     Result r = filterClient->close();
     filterClient->decStrong(filter);
-       env->SetLongField(filter, gFields.sharedFilterContext, 0);
     if (shared) {
+        env->SetLongField(filter, gFields.sharedFilterContext, 0);
     } else {
         env->SetLongField(filter, gFields.filterContext, 0);
     }
@@ -3890,22 +3905,22 @@
     return (jint)r;
 }
 
-static jstring android_media_tv_Tuner_create_shared_filter(JNIEnv *env, jobject filter) {
+static jstring android_media_tv_Tuner_acquire_shared_filter_token(JNIEnv *env, jobject filter) {
     sp<FilterClient> filterClient = getFilterClient(env, filter);
     if (filterClient == nullptr) {
         jniThrowException(env, "java/lang/IllegalStateException",
-                          "Failed to create shared filter: filter client not found");
+                          "Failed to acquire shared filter token: filter client not found");
         return nullptr;
     }
 
-    string token = filterClient->createSharedFilter();
+    string token = filterClient->acquireSharedFilterToken();
     if (token.empty()) {
         return nullptr;
     }
     return env->NewStringUTF(token.data());
 }
 
-static void android_media_tv_Tuner_release_shared_filter(
+static void android_media_tv_Tuner_free_shared_filter_token(
         JNIEnv *env, jobject filter, jstring token) {
     sp<FilterClient> filterClient = getFilterClient(env, filter);
     if (filterClient == nullptr) {
@@ -3915,7 +3930,7 @@
     }
 
     std::string filterToken(env->GetStringUTFChars(token, nullptr));
-    filterClient->releaseSharedFilter(filterToken);
+    filterClient->freeSharedFilterToken(filterToken);
 }
 
 static sp<TimeFilterClient> getTimeFilterClient(JNIEnv *env, jobject filter) {
@@ -4408,10 +4423,10 @@
     { "nativeFlushFilter", "()I", (void *)android_media_tv_Tuner_flush_filter },
     { "nativeRead", "([BJJ)I", (void *)android_media_tv_Tuner_read_filter_fmq },
     { "nativeClose", "()I", (void *)android_media_tv_Tuner_close_filter },
-    {"nativeCreateSharedFilter", "()Ljava/lang/String;",
-            (void *)android_media_tv_Tuner_create_shared_filter},
-    {"nativeReleaseSharedFilter", "(Ljava/lang/String;)V",
-            (void *)android_media_tv_Tuner_release_shared_filter},
+    {"nativeAcquireSharedFilterToken", "()Ljava/lang/String;",
+            (void *)android_media_tv_Tuner_acquire_shared_filter_token},
+    {"nativeFreeSharedFilterToken", "(Ljava/lang/String;)V",
+            (void *)android_media_tv_Tuner_free_shared_filter_token},
 };
 
 static const JNINativeMethod gSharedFilterMethods[] = {
diff --git a/media/jni/tuner/FilterClient.cpp b/media/jni/tuner/FilterClient.cpp
index e8b3de8..8568383 100644
--- a/media/jni/tuner/FilterClient.cpp
+++ b/media/jni/tuner/FilterClient.cpp
@@ -196,10 +196,10 @@
     return Result::INVALID_STATE;
 }
 
-string FilterClient::createSharedFilter() {
+string FilterClient::acquireSharedFilterToken() {
     if (mTunerFilter != nullptr) {
         string filterToken;
-        if (mTunerFilter->createSharedFilter(&filterToken).isOk()) {
+        if (mTunerFilter->acquireSharedFilterToken(&filterToken).isOk()) {
             return filterToken;
         }
     }
@@ -207,9 +207,9 @@
     return "";
 }
 
-Result FilterClient::releaseSharedFilter(const string& filterToken) {
+Result FilterClient::freeSharedFilterToken(const string& filterToken) {
     if (mTunerFilter != nullptr) {
-        Status s = mTunerFilter->releaseSharedFilter(filterToken);
+        Status s = mTunerFilter->freeSharedFilterToken(filterToken);
         return ClientHelper::getServiceSpecificErrorCode(s);
     }
 
@@ -346,4 +346,13 @@
     mAvSharedMemSize = 0;
     mAvSharedHandle = nullptr;
 }
+
+Result FilterClient::setDelayHint(const FilterDelayHint& hint) {
+    if (mTunerFilter) {
+        Status s = mTunerFilter->setDelayHint(hint);
+        return ClientHelper::getServiceSpecificErrorCode(s);
+    }
+    return Result::INVALID_STATE;
+}
+
 }  // namespace android
diff --git a/media/jni/tuner/FilterClient.h b/media/jni/tuner/FilterClient.h
index c031b2a..20e5610 100644
--- a/media/jni/tuner/FilterClient.h
+++ b/media/jni/tuner/FilterClient.h
@@ -33,6 +33,7 @@
 using ::aidl::android::hardware::tv::tuner::DemuxFilterSettings;
 using ::aidl::android::hardware::tv::tuner::DemuxFilterStatus;
 using ::aidl::android::hardware::tv::tuner::DemuxFilterType;
+using ::aidl::android::hardware::tv::tuner::FilterDelayHint;
 using ::aidl::android::media::tv::tuner::BnTunerFilterCallback;
 using ::aidl::android::media::tv::tuner::ITunerFilter;
 using ::android::hardware::EventFlag;
@@ -143,14 +144,19 @@
     Result close();
 
     /**
-     * Create a new SharedFiler.
+     * Accquire a new SharedFiler token.
      */
-    string createSharedFilter();
+    string acquireSharedFilterToken();
 
     /**
-     * Release SharedFiler.
+     * Release SharedFiler token.
      */
-    Result releaseSharedFilter(const string& filterToken);
+    Result freeSharedFilterToken(const string& filterToken);
+
+    /**
+     * Set a filter delay hint.
+     */
+    Result setDelayHint(const FilterDelayHint& hint);
 
 private:
     Result getFilterMq();
diff --git a/media/native/midi/amidi.cpp b/media/native/midi/amidi.cpp
index 923377c..f90796e 100644
--- a/media/native/midi/amidi.cpp
+++ b/media/native/midi/amidi.cpp
@@ -325,8 +325,8 @@
         }
 
         uint8_t readBuffer[AMIDI_PACKET_SIZE];
-        ssize_t readCount = read(mPort->ufd, readBuffer, sizeof(readBuffer));
-        if (readCount == EINTR || readCount < 1) {
+        ssize_t readCount = TEMP_FAILURE_RETRY(read(mPort->ufd, readBuffer, sizeof(readBuffer)));
+        if (readCount < 1) {
             return  AMEDIA_ERROR_UNKNOWN;
         }
 
@@ -407,7 +407,8 @@
 
         ssize_t numTransferBytes =
                 AMIDI_makeSendBuffer(writeBuffer, data + numSent, blockSize, timestamp);
-        ssize_t numWritten = write(((AMIDI_Port*)inputPort)->ufd, writeBuffer, numTransferBytes);
+        ssize_t numWritten = TEMP_FAILURE_RETRY(write(((AMIDI_Port*)inputPort)->ufd, writeBuffer,
+                                                      numTransferBytes));
         if (numWritten < 0) {
             break;  // error so bail out.
         }
@@ -430,7 +431,8 @@
 
     uint8_t opCode = AMIDI_OPCODE_FLUSH;
     ssize_t numTransferBytes = 1;
-    ssize_t numWritten = write(((AMIDI_Port*)inputPort)->ufd, &opCode, numTransferBytes);
+    ssize_t numWritten = TEMP_FAILURE_RETRY(write(((AMIDI_Port*)inputPort)->ufd, &opCode,
+                                                  numTransferBytes));
 
     if (numWritten < numTransferBytes) {
         ALOGE("AMidiInputPort_flush Couldn't write MIDI flush. requested:%zd, written:%zd",
diff --git a/omapi/aidl/Android.bp b/omapi/aidl/Android.bp
new file mode 100644
index 0000000..2b81200
--- /dev/null
+++ b/omapi/aidl/Android.bp
@@ -0,0 +1,35 @@
+// 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.
+
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aidl_interface {
+    name: "android.se.omapi",
+    vendor_available: true,
+    srcs: ["android/se/omapi/*.aidl"],
+    stability: "vintf",
+    backend: {
+        java: {
+            sdk_version: "module_current",
+        },
+        rust: {
+            enabled: true,
+        },
+        ndk: {
+            separate_platform_variant: false,
+        },
+    },
+}
diff --git a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementChannel.aidl b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementChannel.aidl
new file mode 100644
index 0000000..725013a
--- /dev/null
+++ b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementChannel.aidl
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021, 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.
+ *//*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.se.omapi;
+/* @hide */
+@VintfStability
+interface ISecureElementChannel {
+  void close();
+  boolean isClosed();
+  boolean isBasicChannel();
+  byte[] getSelectResponse();
+  byte[] transmit(in byte[] command);
+  boolean selectNext();
+}
diff --git a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementListener.aidl b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementListener.aidl
new file mode 100644
index 0000000..77e1c53f
--- /dev/null
+++ b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementListener.aidl
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *//*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.se.omapi;
+/* @hide */
+@VintfStability
+interface ISecureElementListener {
+}
diff --git a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementReader.aidl b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementReader.aidl
new file mode 100644
index 0000000..2b10c47
--- /dev/null
+++ b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementReader.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *//*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.se.omapi;
+/* @hide */
+@VintfStability
+interface ISecureElementReader {
+  boolean isSecureElementPresent();
+  android.se.omapi.ISecureElementSession openSession();
+  void closeSessions();
+  boolean reset();
+}
diff --git a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementService.aidl b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementService.aidl
new file mode 100644
index 0000000..0c8e431
--- /dev/null
+++ b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementService.aidl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *//*
+ * Copyright (c) 2015-2017, The Linux Foundation.
+ *//*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.se.omapi;
+/* @hide */
+@VintfStability
+interface ISecureElementService {
+  String[] getReaders();
+  android.se.omapi.ISecureElementReader getReader(in String reader);
+  boolean[] isNfcEventAllowed(in String reader, in byte[] aid, in String[] packageNames, in int userId);
+}
diff --git a/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementSession.aidl b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementSession.aidl
new file mode 100644
index 0000000..06287c5
--- /dev/null
+++ b/omapi/aidl/aidl_api/android.se.omapi/current/android/se/omapi/ISecureElementSession.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *//*
+ * Copyright (c) 2015-2017, The Linux Foundation.
+ *//*
+ * Contributed by: Giesecke & Devrient GmbH.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.se.omapi;
+/* @hide */
+@VintfStability
+interface ISecureElementSession {
+  byte[] getAtr();
+  void close();
+  void closeChannels();
+  boolean isClosed();
+  android.se.omapi.ISecureElementChannel openBasicChannel(in byte[] aid, in byte p2, in android.se.omapi.ISecureElementListener listener);
+  android.se.omapi.ISecureElementChannel openLogicalChannel(in byte[] aid, in byte p2, in android.se.omapi.ISecureElementListener listener);
+}
diff --git a/core/java/android/se/omapi/ISecureElementChannel.aidl b/omapi/aidl/android/se/omapi/ISecureElementChannel.aidl
similarity index 94%
rename from core/java/android/se/omapi/ISecureElementChannel.aidl
rename to omapi/aidl/android/se/omapi/ISecureElementChannel.aidl
index 4ae57ab..bbd3c14 100644
--- a/core/java/android/se/omapi/ISecureElementChannel.aidl
+++ b/omapi/aidl/android/se/omapi/ISecureElementChannel.aidl
@@ -22,6 +22,7 @@
 import android.se.omapi.ISecureElementSession;
 
 /** @hide */
+@VintfStability
 interface ISecureElementChannel {
 
     /**
@@ -58,6 +59,9 @@
      * Transmits the specified command APDU and returns the response APDU.
      * MANAGE channel commands are not supported.
      * Selection of applets is not supported in logical channels.
+     *
+     * @param command Command APDU, its structure is defined in  ISO/IEC 7816-4
+     *                in Standard byte format
      */
     byte[] transmit(in byte[] command);
 
diff --git a/core/java/android/se/omapi/ISecureElementListener.aidl b/omapi/aidl/android/se/omapi/ISecureElementListener.aidl
similarity index 97%
rename from core/java/android/se/omapi/ISecureElementListener.aidl
rename to omapi/aidl/android/se/omapi/ISecureElementListener.aidl
index e9dd181..479dcd7 100644
--- a/core/java/android/se/omapi/ISecureElementListener.aidl
+++ b/omapi/aidl/android/se/omapi/ISecureElementListener.aidl
@@ -23,5 +23,6 @@
  * Interface to receive call-backs when the service is connected.
  * @hide
  */
+@VintfStability
 interface ISecureElementListener {
 }
diff --git a/core/java/android/se/omapi/ISecureElementReader.aidl b/omapi/aidl/android/se/omapi/ISecureElementReader.aidl
similarity index 94%
rename from core/java/android/se/omapi/ISecureElementReader.aidl
rename to omapi/aidl/android/se/omapi/ISecureElementReader.aidl
index 41244ab..a6979fa 100644
--- a/core/java/android/se/omapi/ISecureElementReader.aidl
+++ b/omapi/aidl/android/se/omapi/ISecureElementReader.aidl
@@ -22,6 +22,7 @@
 import android.se.omapi.ISecureElementSession;
 
 /** @hide */
+@VintfStability
 interface ISecureElementReader {
 
     /**
@@ -34,7 +35,7 @@
      * Connects to a secure element in this reader. <br>
      * This method prepares (initialises) the Secure Element for communication
      * before the Session object is returned (e.g. powers the Secure Element by
-     * ICC ON if its not already on). There might be multiple sessions opened at
+     * ICC ON if it is not already on). There might be multiple sessions opened at
      * the same time on the same reader. The system ensures the interleaving of
      * APDUs between the respective sessions.
      *
diff --git a/core/java/android/se/omapi/ISecureElementService.aidl b/omapi/aidl/android/se/omapi/ISecureElementService.aidl
similarity index 66%
rename from core/java/android/se/omapi/ISecureElementService.aidl
rename to omapi/aidl/android/se/omapi/ISecureElementService.aidl
index 4fa799e..13707ec 100644
--- a/core/java/android/se/omapi/ISecureElementService.aidl
+++ b/omapi/aidl/android/se/omapi/ISecureElementService.aidl
@@ -28,23 +28,31 @@
  * SecureElement service interface.
  * @hide
  */
+@VintfStability
 interface ISecureElementService {
 
     /**
      * Returns the friendly names of available Secure Element readers.
+     * <ul>
+     * <li>If the reader is a SIM reader, then its name must be "SIM[Slot]".</li>
+     * <li>If the reader is a SD or micro SD reader, then its name must be "SD[Slot]"</li>
+     * <li>If the reader is a embedded SE reader, then its name must be "eSE[Slot]"</li>
+     * </ul>
+     * Slot is a decimal number without leading zeros. The Numbering must start with 1
+     * (e.g. SIM1, SIM2, ... or SD1, SD2, ... or eSE1, eSE2, ...).
      */
     String[] getReaders();
 
     /**
      * Returns SecureElement Service reader object to the given name.
      */
-    ISecureElementReader getReader(String reader);
+    ISecureElementReader getReader(in String reader);
 
     /**
      * Checks if the application defined by the package name is allowed to
      * receive NFC transaction events for the defined AID.
      */
-    boolean[] isNFCEventAllowed(String reader, in byte[] aid,
-            in String[] packageNames);
+    boolean[] isNfcEventAllowed(in String reader, in byte[] aid,
+            in String[] packageNames, in int userId);
 
 }
diff --git a/core/java/android/se/omapi/ISecureElementSession.aidl b/omapi/aidl/android/se/omapi/ISecureElementSession.aidl
similarity index 84%
rename from core/java/android/se/omapi/ISecureElementSession.aidl
rename to omapi/aidl/android/se/omapi/ISecureElementSession.aidl
index 8ea599f..129ecc4 100644
--- a/core/java/android/se/omapi/ISecureElementSession.aidl
+++ b/omapi/aidl/android/se/omapi/ISecureElementSession.aidl
@@ -27,6 +27,7 @@
 import android.se.omapi.ISecureElementListener;
 
 /** @hide */
+@VintfStability
 interface ISecureElementSession {
 
     /**
@@ -45,7 +46,6 @@
      */
     void closeChannels();
 
-
     /**
      * Tells if this session is closed.
      *
@@ -59,15 +59,19 @@
      * applet if aid != null.
      * Logical channels cannot be opened with this connection.
      * Use interface method openLogicalChannel() to open a logical channel.
+     * Listener is passed to secure element service and used to monitor whether
+     * the client application that uses OMAPI is still alive or not.
      */
     ISecureElementChannel openBasicChannel(in byte[] aid, in byte p2,
-            ISecureElementListener listener);
+            in ISecureElementListener listener);
 
     /**
      * Opens a connection using the next free logical channel of the card in the
      * specified reader. Selects the specified applet.
      * Selection of other applets with this connection is not supported.
+     * Listener is passed to secure element service and used to monitor whether
+     * the client application that uses OMAPI is still alive or not.
      */
     ISecureElementChannel openLogicalChannel(in byte[] aid, in byte p2,
-            ISecureElementListener listener);
+            in ISecureElementListener listener);
 }
diff --git a/omapi/aidl/vts/functional/AccessControlApp/Android.bp b/omapi/aidl/vts/functional/AccessControlApp/Android.bp
new file mode 100644
index 0000000..f03c3f6
--- /dev/null
+++ b/omapi/aidl/vts/functional/AccessControlApp/Android.bp
@@ -0,0 +1,54 @@
+//
+// Copyright (C) 2021 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "VtsHalOmapiSeAccessControlTestCases",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsHalOmapiSeAccessControlTestCases.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libnativehelper",
+        "libutils",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+        "android.se.omapi-V1-ndk",
+    ],
+    cflags: [
+        "-O0",
+        "-g",
+        "-Wall",
+        "-Werror",
+    ],
+    require_root: true,
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/omapi/aidl/vts/functional/AccessControlApp/VtsHalOmapiSeAccessControlTestCases.cpp b/omapi/aidl/vts/functional/AccessControlApp/VtsHalOmapiSeAccessControlTestCases.cpp
new file mode 100644
index 0000000..9ea6543
--- /dev/null
+++ b/omapi/aidl/vts/functional/AccessControlApp/VtsHalOmapiSeAccessControlTestCases.cpp
@@ -0,0 +1,428 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/se/omapi/BnSecureElementListener.h>
+#include <aidl/android/se/omapi/ISecureElementChannel.h>
+#include <aidl/android/se/omapi/ISecureElementListener.h>
+#include <aidl/android/se/omapi/ISecureElementReader.h>
+#include <aidl/android/se/omapi/ISecureElementService.h>
+#include <aidl/android/se/omapi/ISecureElementSession.h>
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <utils/String16.h>
+
+using namespace std;
+using namespace ::testing;
+using namespace android;
+
+int main(int argc, char** argv) {
+    InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    return status;
+}
+
+namespace {
+
+class OMAPISEAccessControlTest : public TestWithParam<std::string> {
+   protected:
+
+    class SEListener : public ::aidl::android::se::omapi::BnSecureElementListener {};
+
+    /**
+     * Verifies TLV data
+     *
+     * @return true if the data is tlv formatted, false otherwise
+     */
+    bool verifyBerTlvData(std::vector<uint8_t> tlv) {
+        if (tlv.size() == 0) {
+            LOG(ERROR) << "Invalid tlv, null";
+            return false;
+        }
+        int i = 0;
+        if ((tlv[i++] & 0x1F) == 0x1F) {
+            // extra byte for TAG field
+            i++;
+        }
+
+        int len = tlv[i++] & 0xFF;
+        if (len > 127) {
+            // more than 1 byte for length
+            int bytesLength = len - 128;
+            len = 0;
+            for (int j = bytesLength; j > 0; j--) {
+                len += (len << 8) + (tlv[i++] & 0xFF);
+            }
+        }
+        // Additional 2 bytes for the SW
+        return (tlv.size() == (i + len + 2));
+    }
+
+    void testSelectableAid(
+            std::vector<std::vector<uint8_t>> authorizedAids) {
+        for (auto aid : authorizedAids) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            auto seListener = ndk::SharedRefBase::make<SEListener>();
+
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    std::vector<uint8_t> selectResponse = {};
+                    ASSERT_NE(reader, nullptr) << "reader is null";
+
+                    bool status = false;
+                    auto res = reader->isSecureElementPresent(&status);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_TRUE(status);
+
+                    res = reader->openSession(&session);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(session, nullptr) << "Could not open session";
+
+                    res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+                    res = channel->getSelectResponse(&selectResponse);
+                    ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+                    ASSERT_GE(selectResponse.size(), 2);
+
+                    if (channel != nullptr) channel->close();
+                    if (session != nullptr) session->close();
+
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 1] & 0xFF), (0x00));
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 2] & 0xFF), (0x90));
+                    ASSERT_TRUE(
+                        verifyBerTlvData(selectResponse)) << "Select Response is not complete";
+                }
+            }
+        }
+    }
+
+    void testUnauthorisedAid(
+            std::vector<std::vector<uint8_t>> unAuthorizedAids) {
+        for (auto aid : unAuthorizedAids) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            auto seListener = ndk::SharedRefBase::make<SEListener>();
+
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    ASSERT_NE(reader, nullptr) << "reader is null";
+
+                    bool status = false;
+                    auto res = reader->isSecureElementPresent(&status);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_TRUE(status);
+
+                    res = reader->openSession(&session);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(session, nullptr) << "Could not open session";
+
+                    res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+
+                    if (channel != nullptr) channel->close();
+                    if (session != nullptr) session->close();
+
+                    if (!res.isOk()) {
+                        ASSERT_EQ(res.getExceptionCode(), EX_SECURITY);
+                        ASSERT_FALSE(res.isOk()) << "expected failed status for this test";
+                    }
+                }
+            }
+        }
+    }
+
+    void testTransmitAPDU(
+            std::vector<uint8_t> aid,
+            std::vector<std::vector<uint8_t>> apdus) {
+        for (auto apdu : apdus) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            auto seListener = ndk::SharedRefBase::make<SEListener>();
+
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    ASSERT_NE(reader, nullptr) << "reader is null";
+                    bool status = false;
+                    std::vector<uint8_t> selectResponse = {};
+                    std::vector<uint8_t> transmitResponse = {};
+                    auto res = reader->isSecureElementPresent(&status);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_TRUE(status);
+
+                    res = reader->openSession(&session);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(session, nullptr) << "Could not open session";
+
+                    res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+                    res = channel->getSelectResponse(&selectResponse);
+                    ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+                    ASSERT_GE(selectResponse.size(), 2);
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 1] & 0xFF), (0x00));
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 2] & 0xFF), (0x90));
+                    ASSERT_TRUE(
+                        verifyBerTlvData(selectResponse)) << "Select Response is not complete";
+
+                    res = channel->transmit(apdu, &transmitResponse);
+                    LOG(INFO) << "STATUS OF TRNSMIT: " << res.getExceptionCode()
+                              << " Message: " << res.getMessage();
+                    if (channel != nullptr) channel->close();
+                    if (session != nullptr) session->close();
+                    ASSERT_TRUE(res.isOk()) << "failed to transmit";
+                }
+            }
+        }
+    }
+
+    void testUnauthorisedAPDU(
+            std::vector<uint8_t> aid,
+            std::vector<std::vector<uint8_t>> apdus) {
+        for (auto apdu : apdus) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            auto seListener = ndk::SharedRefBase::make<SEListener>();
+
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    ASSERT_NE(reader, nullptr) << "reader is null";
+                    bool status = false;
+                    std::vector<uint8_t> selectResponse = {};
+                    std::vector<uint8_t> transmitResponse = {};
+                    auto res = reader->isSecureElementPresent(&status);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_TRUE(status);
+
+                    res = reader->openSession(&session);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(session, nullptr) << "Could not open session";
+
+                    res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+                    ASSERT_TRUE(res.isOk()) << res.getMessage();
+                    ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+                    res = channel->getSelectResponse(&selectResponse);
+                    ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+                    ASSERT_GE(selectResponse.size(), 2);
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 1] & 0xFF), (0x00));
+                    ASSERT_EQ((selectResponse[selectResponse.size() - 2] & 0xFF), (0x90));
+                    ASSERT_TRUE(
+                        verifyBerTlvData(selectResponse)) << "Select Response is not complete";
+
+                    res = channel->transmit(apdu, &transmitResponse);
+                    LOG(INFO) << "STATUS OF TRNSMIT: " << res.getExceptionCode()
+                              << " Message: " << res.getMessage();
+
+                    if (channel != nullptr) channel->close();
+                    if (session != nullptr) session->close();
+                    if (!res.isOk()) {
+                        ASSERT_EQ(res.getExceptionCode(), EX_SECURITY);
+                        ASSERT_FALSE(res.isOk()) << "expected failed status for this test";
+                    }
+                }
+            }
+        }
+    }
+
+    bool supportOMAPIReaders() {
+        return (deviceSupportsFeature(FEATURE_SE_OMAPI_ESE.c_str()));
+    }
+
+    void getFirstApiLevel(int32_t* outApiLevel) {
+        int32_t firstApiLevel = property_get_int32(FEATURE_SE_API_LEVEL.c_str(), -1);
+        if (firstApiLevel < 0) {
+            firstApiLevel = property_get_int32(FEATURE_SE_SDK_VERSION.c_str(), -1);
+        }
+        ASSERT_GT(firstApiLevel, 0);  // first_api_level must exist
+        *outApiLevel = firstApiLevel;
+        return;
+    }
+
+    bool supportsHardware() {
+        bool lowRamDevice = property_get_bool(FEATURE_SE_LOW_RAM.c_str(), true);
+        return !lowRamDevice || deviceSupportsFeature(FEATURE_SE_HARDWARE_WATCH.c_str()) ||
+                deviceSupportsFeature(FEATURE_SE_OMAPI_SERVICE.c_str());  // android.se.omapi
+    }
+
+    void SetUp() override {
+        ASSERT_TRUE(supportsHardware());
+        int32_t apiLevel;
+        getFirstApiLevel(&apiLevel);
+        ASSERT_TRUE(apiLevel > 27);
+        ASSERT_TRUE(supportOMAPIReaders());
+        LOG(INFO) << "get OMAPI service with name:" << GetParam();
+        ::ndk::SpAIBinder ks2Binder(AServiceManager_getService(GetParam().c_str()));
+        mOmapiSeService = aidl::android::se::omapi::ISecureElementService::fromBinder(ks2Binder);
+        ASSERT_TRUE(mOmapiSeService);
+
+        std::vector<std::string> readers = {};
+
+        if (mOmapiSeService != NULL) {
+            auto status = mOmapiSeService->getReaders(&readers);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+            for (auto readerName : readers) {
+                // Filter eSE readers only
+                if (readerName.find(ESE_READER_PREFIX, 0) != std::string::npos) {
+                    std::shared_ptr<::aidl::android::se::omapi::ISecureElementReader> reader;
+                    status = mOmapiSeService->getReader(readerName, &reader);
+                    ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+                    mVSReaders[readerName] = reader;
+                }
+            }
+        }
+    }
+
+    void TearDown() override {
+        if (mOmapiSeService != nullptr) {
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    reader->closeSessions();
+                }
+            }
+        }
+    }
+
+    static inline std::string const ESE_READER_PREFIX = "eSE";
+    static inline std::string const FEATURE_SE_OMAPI_ESE = "android.hardware.se.omapi.ese";
+    static inline std::string const FEATURE_SE_LOW_RAM = "ro.config.low_ram";
+    static inline std::string const FEATURE_SE_HARDWARE_WATCH = "android.hardware.type.watch";
+    static inline std::string const FEATURE_SE_OMAPI_SERVICE = "com.android.se";
+    static inline std::string const FEATURE_SE_SDK_VERSION = "ro.build.version.sdk";
+    static inline std::string const FEATURE_SE_API_LEVEL = "ro.product.first_api_level";
+
+    std::vector<uint8_t> AID_40 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x40};
+    std::vector<uint8_t> AID_41 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x41};
+    std::vector<uint8_t> AID_42 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x42};
+    std::vector<uint8_t> AID_43 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x43};
+    std::vector<uint8_t> AID_44 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x44};
+    std::vector<uint8_t> AID_45 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x45};
+    std::vector<uint8_t> AID_46 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x46};
+    std::vector<uint8_t> AID_47 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x47};
+    std::vector<uint8_t> AID_48 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x48};
+    std::vector<uint8_t> AID_49 = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x49};
+    std::vector<uint8_t> AID_4A = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4A};
+    std::vector<uint8_t> AID_4B = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4B};
+    std::vector<uint8_t> AID_4C = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4C};
+    std::vector<uint8_t> AID_4D = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4D};
+    std::vector<uint8_t> AID_4E = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4E};
+    std::vector<uint8_t> AID_4F = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                   0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x4F};
+
+    std::vector<std::vector<uint8_t>> AUTHORIZED_AID = {AID_40, AID_41, AID_42, AID_44, AID_45,
+                                                        AID_47, AID_48, AID_49, AID_4A, AID_4B,
+                                                        AID_4C, AID_4D, AID_4E, AID_4F};
+    std::vector<std::vector<uint8_t>> UNAUTHORIZED_AID = {AID_43, AID_46};
+
+    /* Authorized APDU for AID_40 */
+    std::vector<std::vector<uint8_t>> AUTHORIZED_APDU_AID_40 = {
+        {0x00, 0x06, 0x00, 0x00},
+        {0xA0, 0x06, 0x00, 0x00},
+    };
+    /* Unauthorized APDU for AID_40 */
+    std::vector<std::vector<uint8_t>> UNAUTHORIZED_APDU_AID_40 = {
+        {0x00, 0x08, 0x00, 0x00, 0x00},
+        {0x80, 0x06, 0x00, 0x00},
+        {0xA0, 0x08, 0x00, 0x00, 0x00},
+        {0x94, 0x06, 0x00, 0x00, 0x00},
+    };
+
+    /* Authorized APDU for AID_41 */
+    std::vector<std::vector<uint8_t>> AUTHORIZED_APDU_AID_41 = {
+        {0x94, 0x06, 0x00, 0x00},
+        {0x94, 0x08, 0x00, 0x00, 0x00},
+        {0x94, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+        {0x94, 0x0A, 0x00, 0x00, 0x01, 0xAA}};
+    /* Unauthorized APDU for AID_41 */
+    std::vector<std::vector<uint8_t>> UNAUTHORIZED_APDU_AID_41 = {
+        {0x00, 0x06, 0x00, 0x00},
+        {0x80, 0x06, 0x00, 0x00},
+        {0xA0, 0x06, 0x00, 0x00},
+        {0x00, 0x08, 0x00, 0x00, 0x00},
+        {0x00, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+        {0x80, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+        {0xA0, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+        {0x80, 0x08, 0x00, 0x00, 0x00},
+        {0xA0, 0x08, 0x00, 0x00, 0x00},
+        {0x00, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+        {0x80, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+        {0xA0, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+    };
+
+    std::shared_ptr<aidl::android::se::omapi::ISecureElementService> mOmapiSeService;
+
+    std::map<std::string, std::shared_ptr<aidl::android::se::omapi::ISecureElementReader>>
+        mVSReaders = {};
+};
+
+TEST_P(OMAPISEAccessControlTest, TestAuthorizedAID) {
+    testSelectableAid(AUTHORIZED_AID);
+}
+
+TEST_P(OMAPISEAccessControlTest, TestUnauthorizedAID) {
+    testUnauthorisedAid(UNAUTHORIZED_AID);
+}
+
+TEST_P(OMAPISEAccessControlTest, TestAuthorizedAPDUAID40) {
+    testTransmitAPDU(AID_40, AUTHORIZED_APDU_AID_40);
+}
+
+TEST_P(OMAPISEAccessControlTest, TestUnauthorisedAPDUAID40) {
+    testUnauthorisedAPDU(AID_40, UNAUTHORIZED_APDU_AID_40);
+}
+
+TEST_P(OMAPISEAccessControlTest, TestAuthorizedAPDUAID41) {
+    testTransmitAPDU(AID_41, AUTHORIZED_APDU_AID_41);
+}
+
+TEST_P(OMAPISEAccessControlTest, TestUnauthorisedAPDUAID41) {
+    testUnauthorisedAPDU(AID_41, UNAUTHORIZED_APDU_AID_41);
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, OMAPISEAccessControlTest,
+                         testing::ValuesIn(::android::getAidlHalInstanceNames(
+                             aidl::android::se::omapi::ISecureElementService::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OMAPISEAccessControlTest);
+
+}  // namespace
diff --git a/omapi/aidl/vts/functional/omapi/Android.bp b/omapi/aidl/vts/functional/omapi/Android.bp
new file mode 100644
index 0000000..c3ab8d1
--- /dev/null
+++ b/omapi/aidl/vts/functional/omapi/Android.bp
@@ -0,0 +1,54 @@
+//
+// Copyright (C) 2021 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 {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+    name: "VtsHalOmapiSeServiceV1_TargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsHalOmapiSeServiceV1_TargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libcutils",
+        "libhidlbase",
+        "libnativehelper",
+        "libutils",
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+        "android.se.omapi-V1-ndk",
+    ],
+    cflags: [
+        "-O0",
+        "-g",
+        "-Wall",
+        "-Werror",
+    ],
+    require_root: true,
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp
new file mode 100644
index 0000000..319cb7e
--- /dev/null
+++ b/omapi/aidl/vts/functional/omapi/VtsHalOmapiSeServiceV1_TargetTest.cpp
@@ -0,0 +1,609 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <aidl/android/se/omapi/BnSecureElementListener.h>
+#include <aidl/android/se/omapi/ISecureElementChannel.h>
+#include <aidl/android/se/omapi/ISecureElementListener.h>
+#include <aidl/android/se/omapi/ISecureElementReader.h>
+#include <aidl/android/se/omapi/ISecureElementService.h>
+#include <aidl/android/se/omapi/ISecureElementSession.h>
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <binder/IServiceManager.h>
+#include <cutils/properties.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <utils/String16.h>
+
+using namespace std;
+using namespace ::testing;
+using namespace android;
+
+int main(int argc, char** argv) {
+    InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    return status;
+}
+
+namespace {
+
+class OMAPISEServiceHalTest : public TestWithParam<std::string> {
+   protected:
+    class SEListener : public ::aidl::android::se::omapi::BnSecureElementListener {};
+
+    void testSelectableAid(
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> reader,
+        std::vector<uint8_t> aid, std::vector<uint8_t>& selectResponse) {
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+        auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+
+        ASSERT_NE(reader, nullptr) << "reader is null";
+
+        bool status = false;
+        auto res = reader->isSecureElementPresent(&status);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_TRUE(status);
+
+        res = reader->openSession(&session);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_NE(session, nullptr) << "Could not open session";
+
+        res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+        res = channel->getSelectResponse(&selectResponse);
+        ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+        ASSERT_GE(selectResponse.size(), 2);
+
+        if (channel != nullptr) channel->close();
+        if (session != nullptr) session->close();
+
+        ASSERT_EQ((selectResponse[selectResponse.size() - 1] & 0xFF), (0x00));
+        ASSERT_EQ((selectResponse[selectResponse.size() - 2] & 0xFF), (0x90));
+    }
+
+    void testNonSelectableAid(
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> reader,
+        std::vector<uint8_t> aid) {
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+        auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+
+        ASSERT_NE(reader, nullptr) << "reader is null";
+
+        bool status = false;
+        auto res = reader->isSecureElementPresent(&status);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_TRUE(status);
+
+        res = reader->openSession(&session);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_NE(session, nullptr) << "Could not open session";
+
+        res = session->openLogicalChannel(aid, 0x00, seListener, &channel);
+        if (channel != nullptr) channel->close();
+        if (session != nullptr) session->close();
+
+        LOG(ERROR) << res.getMessage();
+        ASSERT_FALSE(res.isOk()) << "expected to fail to open channel for this test";
+    }
+
+    /**
+     * Verifies TLV data
+     *
+     * @return true if the data is tlv formatted, false otherwise
+     */
+    bool verifyBerTlvData(std::vector<uint8_t> tlv) {
+        if (tlv.size() == 0) {
+            LOG(ERROR) << "Invalid tlv, null";
+            return false;
+        }
+        int i = 0;
+        if ((tlv[i++] & 0x1F) == 0x1F) {
+            // extra byte for TAG field
+            i++;
+        }
+
+        int len = tlv[i++] & 0xFF;
+        if (len > 127) {
+            // more than 1 byte for length
+            int bytesLength = len - 128;
+            len = 0;
+            for (int j = bytesLength; j > 0; j--) {
+                len += (len << 8) + (tlv[i++] & 0xFF);
+            }
+        }
+        // Additional 2 bytes for the SW
+        return (tlv.size() == (i + len + 2));
+    }
+
+    void internalTransmitApdu(
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementReader> reader,
+        std::vector<uint8_t> apdu, std::vector<uint8_t>& transmitResponse) {
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+        std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+        auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+        std::vector<uint8_t> selectResponse = {};
+
+        ASSERT_NE(reader, nullptr) << "reader is null";
+
+        bool status = false;
+        auto res = reader->isSecureElementPresent(&status);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_TRUE(status);
+
+        res = reader->openSession(&session);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_NE(session, nullptr) << "Could not open session";
+
+        res = session->openLogicalChannel(SELECTABLE_AID, 0x00, seListener, &channel);
+        ASSERT_TRUE(res.isOk()) << res.getMessage();
+        ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+        res = channel->getSelectResponse(&selectResponse);
+        ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+        ASSERT_GE(selectResponse.size(), 2);
+
+        res = channel->transmit(apdu, &transmitResponse);
+        if (channel != nullptr) channel->close();
+        if (session != nullptr) session->close();
+        LOG(INFO) << "STATUS OF TRNSMIT: " << res.getExceptionCode()
+                  << " Message: " << res.getMessage();
+        ASSERT_TRUE(res.isOk()) << "failed to transmit";
+    }
+
+    bool supportOMAPIReaders() {
+        return (deviceSupportsFeature(FEATURE_SE_OMAPI_ESE.c_str()));
+    }
+
+    void SetUp() override {
+        LOG(INFO) << "get OMAPI service with name:" << GetParam();
+        ::ndk::SpAIBinder ks2Binder(AServiceManager_getService(GetParam().c_str()));
+        mOmapiSeService = aidl::android::se::omapi::ISecureElementService::fromBinder(ks2Binder);
+        ASSERT_TRUE(mOmapiSeService);
+
+        std::vector<std::string> readers = {};
+
+        if (omapiSecureService() != NULL) {
+            auto status = omapiSecureService()->getReaders(&readers);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+            for (auto readerName : readers) {
+                // Filter eSE readers only
+                if (readerName.find(ESE_READER_PREFIX, 0) != std::string::npos) {
+                    std::shared_ptr<::aidl::android::se::omapi::ISecureElementReader> reader;
+                    status = omapiSecureService()->getReader(readerName, &reader);
+                    ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+                    mVSReaders[readerName] = reader;
+                }
+            }
+        }
+    }
+
+    void TearDown() override {
+        if (mOmapiSeService != nullptr) {
+            if (mVSReaders.size() > 0) {
+                for (const auto& [name, reader] : mVSReaders) {
+                    reader->closeSessions();
+                }
+            }
+        }
+    }
+
+    bool isDebuggableBuild() {
+        char value[PROPERTY_VALUE_MAX] = {0};
+        property_get("ro.system.build.type", value, "");
+        if (strcmp(value, "userdebug") == 0) {
+            return true;
+        }
+        if (strcmp(value, "eng") == 0) {
+            return true;
+        }
+        return false;
+    }
+
+    std::shared_ptr<aidl::android::se::omapi::ISecureElementService> omapiSecureService() {
+        return mOmapiSeService;
+    }
+
+    static inline std::string const ESE_READER_PREFIX = "eSE";
+    static inline std::string const FEATURE_SE_OMAPI_ESE = "android.hardware.se.omapi.ese";
+
+    std::vector<uint8_t> SELECTABLE_AID = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                           0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0x31};
+    std::vector<uint8_t> LONG_SELECT_RESPONSE_AID = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41,
+                                                     0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64,
+                                                     0x43, 0x54, 0x53, 0x32};
+    std::vector<uint8_t> NON_SELECTABLE_AID = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41, 0x6E, 0x64,
+                                               0x72, 0x6F, 0x69, 0x64, 0x43, 0x54, 0x53, 0xFF};
+
+    std::vector<std::vector<uint8_t>> ILLEGAL_COMMANDS_TRANSMIT = {
+        {0x00, 0x70, 0x00, 0x00},
+        {0x00, 0x70, 0x80, 0x00},
+        {0x00, 0xA4, 0x04, 0x04, 0x10, 0x4A, 0x53, 0x52, 0x31, 0x37, 0x37,
+         0x54, 0x65, 0x73, 0x74, 0x65, 0x72, 0x20, 0x31, 0x2E, 0x30}};
+
+    /* OMAPI APDU Test case 1 and 3 */
+    std::vector<std::vector<uint8_t>> NO_DATA_APDU = {{0x00, 0x06, 0x00, 0x00},
+                                                      {0x80, 0x06, 0x00, 0x00},
+                                                      {0xA0, 0x06, 0x00, 0x00},
+                                                      {0x94, 0x06, 0x00, 0x00},
+                                                      {0x00, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+                                                      {0x80, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+                                                      {0xA0, 0x0A, 0x00, 0x00, 0x01, 0xAA},
+                                                      {0x94, 0x0A, 0x00, 0x00, 0x01, 0xAA}};
+
+    /* OMAPI APDU Test case 2 and 4 */
+    std::vector<std::vector<uint8_t>> DATA_APDU = {{0x00, 0x08, 0x00, 0x00, 0x00},
+                                                   {0x80, 0x08, 0x00, 0x00, 0x00},
+                                                   {0xA0, 0x08, 0x00, 0x00, 0x00},
+                                                   {0x94, 0x08, 0x00, 0x00, 0x00},
+                                                   {0x00, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+                                                   {0x80, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+                                                   {0xA0, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00},
+                                                   {0x94, 0x0C, 0x00, 0x00, 0x01, 0xAA, 0x00}};
+
+    /* Case 2 APDU command expects the P2 received in the SELECT command as 1-byte outgoing data */
+    std::vector<uint8_t> CHECK_SELECT_P2_APDU = {0x00, 0xF4, 0x00, 0x00, 0x00};
+
+    /* OMAPI APDU Test case 1 and 3 */
+    std::vector<std::vector<uint8_t>> SW_62xx_NO_DATA_APDU = {{0x00, 0xF3, 0x00, 0x06},
+                                                              {0x00, 0xF3, 0x00, 0x0A, 0x01, 0xAA}};
+
+    /* OMAPI APDU Test case 2 and 4 */
+    std::vector<uint8_t> SW_62xx_DATA_APDU = {0x00, 0xF3, 0x00, 0x08, 0x00};
+    std::vector<uint8_t> SW_62xx_VALIDATE_DATA_APDU = {0x00, 0xF3, 0x00, 0x0C, 0x01, 0xAA, 0x00};
+    std::vector<std::vector<uint8_t>> SW_62xx = {
+        {0x62, 0x00}, {0x62, 0x81}, {0x62, 0x82}, {0x62, 0x83}, {0x62, 0x85}, {0x62, 0xF1},
+        {0x62, 0xF2}, {0x63, 0xF1}, {0x63, 0xF2}, {0x63, 0xC2}, {0x62, 0x02}, {0x62, 0x80},
+        {0x62, 0x84}, {0x62, 0x86}, {0x63, 0x00}, {0x63, 0x81}};
+
+    std::vector<std::vector<uint8_t>> SEGMENTED_RESP_APDU = {
+        // Get response Case2 61FF+61XX with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x00, 0xC2, 0x08, 0x00, 0x00},
+        // Get response Case4 61FF+61XX with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x00, 0xC4, 0x08, 0x00, 0x02, 0x12, 0x34, 0x00},
+        // Get response Case2 6100+61XX with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x00, 0xC6, 0x08, 0x00, 0x00},
+        // Get response Case4 6100+61XX with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x00, 0xC8, 0x08, 0x00, 0x02, 0x12, 0x34, 0x00},
+        // Test device buffer capacity 7FFF data
+        {0x00, 0xC2, 0x7F, 0xFF, 0x00},
+        // Get response 6CFF+61XX with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x00, 0xCF, 0x08, 0x00, 0x00},
+        // Get response with another CLA  with answer length (P1P2) of 0x0800, 2048 bytes
+        {0x94, 0xC2, 0x08, 0x00, 0x00}};
+    long SERVICE_CONNECTION_TIME_OUT = 3000;
+
+    std::shared_ptr<aidl::android::se::omapi::ISecureElementService> mOmapiSeService;
+
+    std::map<std::string, std::shared_ptr<aidl::android::se::omapi::ISecureElementReader>>
+        mVSReaders = {};
+};
+
+/** Tests getReaders API */
+TEST_P(OMAPISEServiceHalTest, TestGetReaders) {
+    std::vector<std::shared_ptr<aidl::android::se::omapi::ISecureElementReader>> eseReaders =
+        {};
+
+    for (const auto& [name, reader] : mVSReaders) {
+        bool status = false;
+        LOG(INFO) << "Name of the reader: " << name;
+
+        if (reader) {
+            auto res = reader->isSecureElementPresent(&status);
+            ASSERT_TRUE(res.isOk()) << res.getMessage();
+        }
+        ASSERT_TRUE(status);
+
+        if (name.find(ESE_READER_PREFIX) == std::string::npos) {
+            LOG(ERROR) << "Incorrect Reader name";
+            FAIL();
+        }
+
+        if (name.find(ESE_READER_PREFIX, 0) != std::string::npos) {
+            eseReaders.push_back(reader);
+        } else {
+            LOG(INFO) << "Reader not supported: " << name;
+            FAIL();
+        }
+    }
+
+    if (deviceSupportsFeature(FEATURE_SE_OMAPI_ESE.c_str())) {
+        ASSERT_GE(eseReaders.size(), 1);
+    } else {
+        ASSERT_TRUE(eseReaders.size() == 0);
+    }
+}
+
+/** Tests OpenBasicChannel API when aid is null */
+TEST_P(OMAPISEServiceHalTest, TestOpenBasicChannelNullAid) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    std::vector<uint8_t> aid = {};
+    auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            bool result = false;
+
+            auto status = reader->openSession(&session);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+            if (!session) {
+                LOG(ERROR) << "Could not open session";
+                FAIL();
+            }
+
+            status = session->openBasicChannel(aid, 0x00, seListener, &channel);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+            if (channel != nullptr) channel->close();
+            if (session != nullptr) session->close();
+
+            if (channel != nullptr) {
+                status = channel->isBasicChannel(&result);
+                ASSERT_TRUE(status.isOk()) << "Basic Channel cannot be opened";
+            }
+        }
+    }
+}
+
+/** Tests OpenBasicChannel API when aid is provided */
+TEST_P(OMAPISEServiceHalTest, TestOpenBasicChannelNonNullAid) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            bool result = false;
+
+            auto status = reader->openSession(&session);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+            if (!session) {
+                LOG(ERROR) << "Could not open session";
+                FAIL();
+            }
+
+            status = session->openBasicChannel(SELECTABLE_AID, 0x00, seListener, &channel);
+            ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+            if (channel != nullptr) channel->close();
+            if (session != nullptr) session->close();
+
+            if (channel != nullptr) {
+                status = channel->isBasicChannel(&result);
+                ASSERT_TRUE(status.isOk()) << "Basic Channel cannot be opened";
+            }
+        }
+    }
+}
+
+/** Tests Select API */
+TEST_P(OMAPISEServiceHalTest, TestSelectableAid) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::vector<uint8_t> selectResponse = {};
+            testSelectableAid(reader, SELECTABLE_AID, selectResponse);
+        }
+    }
+}
+
+/** Tests Select API */
+TEST_P(OMAPISEServiceHalTest, TestLongSelectResponse) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::vector<uint8_t> selectResponse = {};
+            testSelectableAid(reader, LONG_SELECT_RESPONSE_AID, selectResponse);
+            ASSERT_TRUE(verifyBerTlvData(selectResponse)) << "Select Response is not complete";
+        }
+    }
+}
+
+/** Test to fail open channel with wrong aid */
+TEST_P(OMAPISEServiceHalTest, TestWrongAid) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            testNonSelectableAid(reader, NON_SELECTABLE_AID);
+        }
+    }
+}
+
+/** Tests with invalid cmds in Transmit */
+TEST_P(OMAPISEServiceHalTest, TestSecurityExceptionInTransmit) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementSession> session;
+            std::shared_ptr<aidl::android::se::omapi::ISecureElementChannel> channel;
+            auto seListener = ndk::SharedRefBase::make<::OMAPISEServiceHalTest::SEListener>();
+            std::vector<uint8_t> selectResponse = {};
+
+            ASSERT_NE(reader, nullptr) << "reader is null";
+
+            bool status = false;
+            auto res = reader->isSecureElementPresent(&status);
+            ASSERT_TRUE(res.isOk()) << res.getMessage();
+            ASSERT_TRUE(status);
+
+            res = reader->openSession(&session);
+            ASSERT_TRUE(res.isOk()) << res.getMessage();
+            ASSERT_NE(session, nullptr) << "Could not open session";
+
+            res = session->openLogicalChannel(SELECTABLE_AID, 0x00, seListener, &channel);
+            ASSERT_TRUE(res.isOk()) << res.getMessage();
+            ASSERT_NE(channel, nullptr) << "Could not open channel";
+
+            res = channel->getSelectResponse(&selectResponse);
+            ASSERT_TRUE(res.isOk()) << "failed to get Select Response";
+            ASSERT_GE(selectResponse.size(), 2);
+
+            ASSERT_EQ((selectResponse[selectResponse.size() - 1] & 0xFF), (0x00));
+            ASSERT_EQ((selectResponse[selectResponse.size() - 2] & 0xFF), (0x90));
+
+            for (auto cmd : ILLEGAL_COMMANDS_TRANSMIT) {
+                std::vector<uint8_t> response = {};
+                res = channel->transmit(cmd, &response);
+                ASSERT_EQ(res.getExceptionCode(), EX_SECURITY);
+                ASSERT_FALSE(res.isOk()) << "expected failed status for this test";
+            }
+            if (channel != nullptr) channel->close();
+            if (session != nullptr) session->close();
+        }
+    }
+}
+
+/**
+ * Tests Transmit API for all readers.
+ *
+ * Checks the return status and verifies the size of the
+ * response.
+ */
+TEST_P(OMAPISEServiceHalTest, TestTransmitApdu) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            for (auto apdu : NO_DATA_APDU) {
+                std::vector<uint8_t> response = {};
+                internalTransmitApdu(reader, apdu, response);
+                ASSERT_GE(response.size(), 2);
+                ASSERT_EQ((response[response.size() - 1] & 0xFF), (0x00));
+                ASSERT_EQ((response[response.size() - 2] & 0xFF), (0x90));
+            }
+
+            for (auto apdu : DATA_APDU) {
+                std::vector<uint8_t> response = {};
+                internalTransmitApdu(reader, apdu, response);
+                /* 256 byte data and 2 bytes of status word */
+                ASSERT_GE(response.size(), 258);
+                ASSERT_EQ((response[response.size() - 1] & 0xFF), (0x00));
+                ASSERT_EQ((response[response.size() - 2] & 0xFF), (0x90));
+            }
+        }
+    }
+}
+
+/**
+ * Tests if underlying implementations returns the correct Status Word
+ *
+ * TO verify that :
+ * - the device does not modify the APDU sent to the Secure Element
+ * - the warning code is properly received by the application layer as SW answer
+ * - the verify that the application layer can fetch the additionnal data (when present)
+ */
+TEST_P(OMAPISEServiceHalTest, testStatusWordTransmit) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            for (auto apdu : SW_62xx_NO_DATA_APDU) {
+                for (uint8_t i = 0x00; i < SW_62xx.size(); i++) {
+                    apdu[2] = i + 1;
+                    std::vector<uint8_t> response = {};
+                    internalTransmitApdu(reader, apdu, response);
+                    std::vector<uint8_t> SW = SW_62xx[i];
+                    ASSERT_GE(response.size(), 2);
+                    ASSERT_EQ(response[response.size() - 1], SW[1]);
+                    ASSERT_EQ(response[response.size() - 2], SW[0]);
+                }
+            }
+
+            for (uint8_t i = 0x00; i < SW_62xx.size(); i++) {
+                std::vector<uint8_t> apdu = SW_62xx_DATA_APDU;
+                apdu[2] = i + 1;
+                std::vector<uint8_t> response = {};
+                internalTransmitApdu(reader, apdu, response);
+                std::vector<uint8_t> SW = SW_62xx[i];
+                ASSERT_GE(response.size(), 3);
+                ASSERT_EQ(response[response.size() - 1], SW[1]);
+                ASSERT_EQ(response[response.size() - 2], SW[0]);
+            }
+
+            for (uint8_t i = 0x00; i < SW_62xx.size(); i++) {
+                std::vector<uint8_t> apdu = SW_62xx_VALIDATE_DATA_APDU;
+                apdu[2] = i + 1;
+                std::vector<uint8_t> response = {};
+                internalTransmitApdu(reader, apdu, response);
+                ASSERT_GE(response.size(), apdu.size() + 2);
+                std::vector<uint8_t> responseSubstring((response.begin() + 0),
+                                                       (response.begin() + apdu.size()));
+                // We should not care about which channel number is actually assigned.
+                responseSubstring[0] = apdu[0];
+                ASSERT_TRUE((responseSubstring == apdu));
+                std::vector<uint8_t> SW = SW_62xx[i];
+                ASSERT_EQ(response[response.size() - 1], SW[1]);
+                ASSERT_EQ(response[response.size() - 2], SW[0]);
+            }
+        }
+    }
+}
+
+/** Test if the responses are segmented by the underlying implementation */
+TEST_P(OMAPISEServiceHalTest, TestSegmentedResponseTransmit) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            for (auto apdu : SEGMENTED_RESP_APDU) {
+                std::vector<uint8_t> response = {};
+                internalTransmitApdu(reader, apdu, response);
+                int expectedLength = (0x00 << 24) | (0x00 << 16) | (apdu[2] << 8) | apdu[3];
+                ASSERT_EQ(response.size(), (expectedLength + 2));
+                ASSERT_EQ((response[response.size() - 1] & 0xFF), (0x00));
+                ASSERT_EQ((response[response.size() - 2] & 0xFF), (0x90));
+                ASSERT_EQ((response[response.size() - 3] & 0xFF), (0xFF));
+            }
+        }
+    }
+}
+
+/**
+ * Tests the P2 value of the select command.
+ *
+ * Verifies that the default P2 value (0x00) is not modified by the underlying implementation.
+ */
+TEST_P(OMAPISEServiceHalTest, TestP2Value) {
+    ASSERT_TRUE(supportOMAPIReaders() == true);
+    if (mVSReaders.size() > 0) {
+        for (const auto& [name, reader] : mVSReaders) {
+            std::vector<uint8_t> response = {};
+            internalTransmitApdu(reader, CHECK_SELECT_P2_APDU, response);
+            ASSERT_GE(response.size(), 3);
+            ASSERT_EQ((response[response.size() - 1] & 0xFF), (0x00));
+            ASSERT_EQ((response[response.size() - 2] & 0xFF), (0x90));
+            ASSERT_EQ((response[response.size() - 3] & 0xFF), (0x00));
+        }
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, OMAPISEServiceHalTest,
+                         testing::ValuesIn(::android::getAidlHalInstanceNames(
+                             aidl::android::se::omapi::ISecureElementService::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OMAPISEServiceHalTest);
+
+}  // namespace
diff --git a/omapi/java/Android.bp b/omapi/java/Android.bp
new file mode 100644
index 0000000..8d38da0
--- /dev/null
+++ b/omapi/java/Android.bp
@@ -0,0 +1,17 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "frameworks_base_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+filegroup {
+    name: "framework-omapi-sources",
+    srcs: [
+        "**/*.java",
+        "**/*.aidl",
+    ],
+    visibility: ["//frameworks/base"],
+}
diff --git a/core/java/android/se/OWNERS b/omapi/java/android/se/OWNERS
similarity index 100%
rename from core/java/android/se/OWNERS
rename to omapi/java/android/se/OWNERS
diff --git a/core/java/android/se/omapi/Channel.java b/omapi/java/android/se/omapi/Channel.java
similarity index 100%
rename from core/java/android/se/omapi/Channel.java
rename to omapi/java/android/se/omapi/Channel.java
diff --git a/core/java/android/se/omapi/OWNERS b/omapi/java/android/se/omapi/OWNERS
similarity index 100%
rename from core/java/android/se/omapi/OWNERS
rename to omapi/java/android/se/omapi/OWNERS
diff --git a/core/java/android/se/omapi/Reader.java b/omapi/java/android/se/omapi/Reader.java
similarity index 98%
rename from core/java/android/se/omapi/Reader.java
rename to omapi/java/android/se/omapi/Reader.java
index 90c934d..3c2135d9 100644
--- a/core/java/android/se/omapi/Reader.java
+++ b/omapi/java/android/se/omapi/Reader.java
@@ -170,7 +170,9 @@
             try {
                 closeSessions();
                 return mReader.reset();
-            } catch (RemoteException ignore) {return false;}
+            } catch (RemoteException ignore) {
+                return false;
+            }
         }
     }
 }
diff --git a/core/java/android/se/omapi/SEService.java b/omapi/java/android/se/omapi/SEService.java
similarity index 96%
rename from core/java/android/se/omapi/SEService.java
rename to omapi/java/android/se/omapi/SEService.java
index 333af91..f42ca36 100644
--- a/core/java/android/se/omapi/SEService.java
+++ b/omapi/java/android/se/omapi/SEService.java
@@ -230,20 +230,20 @@
       *         is not exist.
       * @return A Reader object for this uicc slot.
       */
-     public @NonNull Reader getUiccReader(int slotNumber) {
-         if (slotNumber < 1) {
-             throw new IllegalArgumentException("slotNumber should be larger than 0");
-         }
-         loadReaders();
+    public @NonNull Reader getUiccReader(int slotNumber) {
+        if (slotNumber < 1) {
+            throw new IllegalArgumentException("slotNumber should be larger than 0");
+        }
+        loadReaders();
 
-         String readerName = UICC_TERMINAL + slotNumber;
-         Reader reader = mReaders.get(readerName);
+        String readerName = UICC_TERMINAL + slotNumber;
+        Reader reader = mReaders.get(readerName);
 
-         if (reader == null) {
+        if (reader == null) {
             throw new IllegalArgumentException("Reader:" + readerName + " doesn't exist");
-         }
+        }
 
-         return reader;
+        return reader;
     }
 
     /**
diff --git a/core/java/android/se/omapi/Session.java b/omapi/java/android/se/omapi/Session.java
similarity index 100%
rename from core/java/android/se/omapi/Session.java
rename to omapi/java/android/se/omapi/Session.java
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/BackupEncryptionService.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/BackupEncryptionService.java
deleted file mode 100644
index 84fb0e6..0000000
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/BackupEncryptionService.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.backup.encryption;
-
-import android.app.Service;
-import android.content.Intent;
-import android.os.IBinder;
-import android.util.Log;
-
-import com.android.internal.backup.IBackupTransport;
-import com.android.server.backup.encryption.transport.IntermediateEncryptingTransport;
-import com.android.server.backup.encryption.transport.IntermediateEncryptingTransportManager;
-
-/**
- * This service provides encryption of backup data. For an intent used to bind to this service, it
- * provides an {@link IntermediateEncryptingTransport} which is an implementation of {@link
- * IBackupTransport} that encrypts (or decrypts) the data when sending it (or receiving it) from the
- * real {@link IBackupTransport}.
- */
-public class BackupEncryptionService extends Service {
-    public static final String TAG = "BackupEncryption";
-    private static IntermediateEncryptingTransportManager sTransportManager = null;
-
-    @Override
-    public void onCreate() {
-        Log.i(TAG, "onCreate:" + this);
-        if (sTransportManager == null) {
-            Log.i(TAG, "Creating IntermediateEncryptingTransportManager");
-            sTransportManager = new IntermediateEncryptingTransportManager(this);
-        }
-    }
-
-    @Override
-    public void onDestroy() {
-        Log.i(TAG, "onDestroy:" + this);
-    }
-
-    @Override
-    public IBinder onBind(Intent intent) {
-        // TODO (b141536117): Check connection with TransportClient.connect and return null on fail.
-        return sTransportManager.get(intent);
-    }
-
-    @Override
-    public boolean onUnbind(Intent intent) {
-        sTransportManager.cleanup(intent);
-        return false;
-    }
-}
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/KeyValueEncrypter.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/KeyValueEncrypter.java
index 1d841b4..db2dd2f 100644
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/KeyValueEncrypter.java
+++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/KeyValueEncrypter.java
@@ -16,8 +16,6 @@
 
 package com.android.server.backup.encryption;
 
-import static com.android.server.backup.encryption.BackupEncryptionService.TAG;
-
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
@@ -36,6 +34,8 @@
 import java.util.Map;
 
 public class KeyValueEncrypter {
+    private static final String TAG = "KeyValueEncrypter";
+
     private final Context mContext;
     private final EncryptionKeyHelper mKeyHelper;
 
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransport.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransport.java
deleted file mode 100644
index c3cb335..0000000
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransport.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.backup.encryption.transport;
-
-import static com.android.server.backup.encryption.BackupEncryptionService.TAG;
-
-import android.app.backup.BackupTransport;
-import android.app.backup.RestoreDescription;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.backup.IBackupTransport;
-import com.android.server.backup.encryption.KeyValueEncrypter;
-import com.android.server.backup.transport.DelegatingTransport;
-import com.android.server.backup.transport.TransportClient;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * This is an implementation of {@link IBackupTransport} that encrypts (or decrypts) the data when
- * sending it (or receiving it) from the {@link IBackupTransport} returned by {@link
- * TransportClient.connect(String)}.
- */
-public class IntermediateEncryptingTransport extends DelegatingTransport {
-    private static final String BACKUP_TEMP_DIR = "backup";
-    private static final String RESTORE_TEMP_DIR = "restore";
-
-    private final TransportClient mTransportClient;
-    private final Object mConnectLock = new Object();
-    private final Context mContext;
-    private volatile IBackupTransport mRealTransport;
-    private AtomicReference<String> mNextRestorePackage = new AtomicReference<>();
-    private final KeyValueEncrypter mKeyValueEncrypter;
-    private final boolean mShouldEncrypt;
-
-    IntermediateEncryptingTransport(
-            TransportClient transportClient, Context context, boolean shouldEncrypt) {
-        this(transportClient, context, new KeyValueEncrypter(context), shouldEncrypt);
-    }
-
-    @VisibleForTesting
-    IntermediateEncryptingTransport(
-            TransportClient transportClient, Context context, KeyValueEncrypter keyValueEncrypter,
-            boolean shouldEncrypt) {
-        mTransportClient = transportClient;
-        mContext = context;
-        mKeyValueEncrypter = keyValueEncrypter;
-        mShouldEncrypt = shouldEncrypt;
-    }
-
-    @Override
-    protected IBackupTransport getDelegate() throws RemoteException {
-        if (mRealTransport == null) {
-            connect();
-        }
-        Log.d(TAG, "real transport = " + mRealTransport.name());
-        return mRealTransport;
-    }
-
-    @Override
-    public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd, int flags)
-            throws RemoteException {
-        if (!mShouldEncrypt) {
-            return super.performBackup(packageInfo, inFd, flags);
-        }
-
-        File encryptedStorageFile = getBackupTempStorage(packageInfo.packageName);
-        if (encryptedStorageFile == null) {
-            return BackupTransport.TRANSPORT_ERROR;
-        }
-
-        // Encrypt the backup data and write it into a temp file.
-        try (OutputStream encryptedOutput = new FileOutputStream(encryptedStorageFile)) {
-            mKeyValueEncrypter.encryptKeyValueData(packageInfo.packageName, inFd,
-                    encryptedOutput);
-        } catch (Throwable e) {
-            Log.e(TAG, "Failed to encrypt backup data: ", e);
-            return BackupTransport.TRANSPORT_ERROR;
-        }
-
-        // Pass the temp file to the real transport for backup.
-        try (FileInputStream encryptedInput = new FileInputStream(encryptedStorageFile)) {
-            return super.performBackup(
-                    packageInfo, ParcelFileDescriptor.dup(encryptedInput.getFD()), flags);
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to read encrypted data from temp storage: ", e);
-            return BackupTransport.TRANSPORT_ERROR;
-        }
-    }
-
-    @Override
-    public int getRestoreData(ParcelFileDescriptor outFd) throws RemoteException {
-        if (!mShouldEncrypt) {
-            return super.getRestoreData(outFd);
-        }
-
-        String nextRestorePackage = mNextRestorePackage.get();
-        if (nextRestorePackage == null) {
-            Log.e(TAG, "No next restore package set");
-            return BackupTransport.TRANSPORT_ERROR;
-        }
-
-        File encryptedStorageFile = getRestoreTempStorage(nextRestorePackage);
-        if (encryptedStorageFile == null) {
-            return BackupTransport.TRANSPORT_ERROR;
-        }
-
-        // Get encrypted restore data from the real transport and write it into a temp file.
-        try (FileOutputStream outputStream = new FileOutputStream(encryptedStorageFile)) {
-            int status = super.getRestoreData(ParcelFileDescriptor.dup(outputStream.getFD()));
-            if (status != BackupTransport.TRANSPORT_OK) {
-                Log.e(TAG, "Failed to read restore data from transport, status = " + status);
-                return status;
-            }
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to write encrypted data to temp storage: ", e);
-            return BackupTransport.TRANSPORT_ERROR;
-        }
-
-        // Decrypt the data and write it into the fd given by the real transport.
-        try (InputStream inputStream = new FileInputStream(encryptedStorageFile)) {
-            mKeyValueEncrypter.decryptKeyValueData(nextRestorePackage, inputStream, outFd);
-            encryptedStorageFile.delete();
-        } catch (Exception e) {
-            Log.e(TAG, "Failed to decrypt restored data: ", e);
-            return BackupTransport.TRANSPORT_ERROR;
-        }
-
-        return BackupTransport.TRANSPORT_OK;
-    }
-
-    @Override
-    public RestoreDescription nextRestorePackage() throws RemoteException {
-        if (!mShouldEncrypt) {
-            return super.nextRestorePackage();
-        }
-
-        RestoreDescription restoreDescription = super.nextRestorePackage();
-        mNextRestorePackage.set(restoreDescription.getPackageName());
-
-        return restoreDescription;
-    }
-
-    @VisibleForTesting
-    protected File getBackupTempStorage(String packageName) {
-        return getTempStorage(packageName, BACKUP_TEMP_DIR);
-    }
-
-    @VisibleForTesting
-    protected File getRestoreTempStorage(String packageName) {
-        return getTempStorage(packageName, RESTORE_TEMP_DIR);
-    }
-
-    private File getTempStorage(String packageName, String operationType) {
-        File encryptedDir = new File(mContext.getFilesDir(), operationType);
-        encryptedDir.mkdir();
-        File encryptedFile = new File(encryptedDir, packageName);
-        try {
-            encryptedFile.createNewFile();
-        } catch (IOException e) {
-            Log.e(TAG, "Failed to create temp file for encrypted data: ", e);
-        }
-        return encryptedFile;
-    }
-
-    private void connect() throws RemoteException {
-        Log.i(TAG, "connecting " + mTransportClient);
-        synchronized (mConnectLock) {
-            if (mRealTransport == null) {
-                mRealTransport = mTransportClient.connect("IntermediateEncryptingTransport");
-                if (mRealTransport == null) {
-                    throw new RemoteException("Could not connect: " + mTransportClient);
-                }
-            }
-        }
-    }
-
-    @VisibleForTesting
-    TransportClient getClient() {
-        return mTransportClient;
-    }
-
-    @VisibleForTesting
-    void setNextRestorePackage(String nextRestorePackage) {
-        mNextRestorePackage.set(nextRestorePackage);
-    }
-}
diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManager.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManager.java
deleted file mode 100644
index 7c4082c..0000000
--- a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManager.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.backup.encryption.transport;
-
-import static com.android.server.backup.encryption.BackupEncryptionService.TAG;
-
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.os.UserHandle;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.backup.IBackupTransport;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.server.backup.transport.TransportClientManager;
-import com.android.server.backup.transport.TransportStats;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/** Handles creation and cleanup of {@link IntermediateEncryptingTransport} instances. */
-public class IntermediateEncryptingTransportManager {
-    private static final String CALLER = "IntermediateEncryptingTransportManager";
-    private final TransportClientManager mTransportClientManager;
-    private final Object mTransportsLock = new Object();
-    private final Map<ComponentName, IntermediateEncryptingTransport> mTransports = new HashMap<>();
-    private Context mContext;
-
-    @VisibleForTesting
-    IntermediateEncryptingTransportManager(TransportClientManager transportClientManager) {
-        mTransportClientManager = transportClientManager;
-    }
-
-    public IntermediateEncryptingTransportManager(Context context) {
-        this(new TransportClientManager(UserHandle.myUserId(), context, new TransportStats()));
-        mContext = context;
-    }
-
-    /**
-     * Extract the {@link ComponentName} corresponding to the real {@link IBackupTransport}, and
-     * provide a {@link IntermediateEncryptingTransport} which is an implementation of {@link
-     * IBackupTransport} that encrypts (or decrypts) the data when sending it (or receiving it) from
-     * the real {@link IBackupTransport}.
-     *
-     * @param intent {@link Intent} created with a call to {@link
-     *     TransportClientManager.getEncryptingTransportIntent(ComponentName)}.
-     * @return
-     */
-    public IntermediateEncryptingTransport get(Intent intent) {
-        Intent transportIntent = TransportClientManager.getRealTransportIntent(intent);
-        Log.i(TAG, "get: intent:" + intent + " transportIntent:" + transportIntent);
-        synchronized (mTransportsLock) {
-            return mTransports.computeIfAbsent(
-                    transportIntent.getComponent(), c -> create(transportIntent));
-        }
-    }
-
-    /** Create an instance of {@link IntermediateEncryptingTransport}. */
-    private IntermediateEncryptingTransport create(Intent realTransportIntent) {
-        Log.d(TAG, "create: intent:" + realTransportIntent);
-
-        LockPatternUtils patternUtils = new LockPatternUtils(mContext);
-        boolean shouldEncrypt =
-                realTransportIntent.getComponent().getClassName().contains("EncryptedLocalTransport")
-                        && (patternUtils.isLockPatternEnabled(UserHandle.myUserId())
-                                || patternUtils.isLockPasswordEnabled(UserHandle.myUserId()));
-
-        return new IntermediateEncryptingTransport(
-                mTransportClientManager.getTransportClient(
-                        realTransportIntent.getComponent(),
-                        realTransportIntent.getExtras(),
-                        CALLER),
-                mContext,
-                shouldEncrypt);
-    }
-
-    /**
-     * Cleanup the {@link IntermediateEncryptingTransport} which was created by a call to {@link
-     * #get(Intent)} with this {@link Intent}.
-     */
-    public void cleanup(Intent intent) {
-        Intent transportIntent = TransportClientManager.getRealTransportIntent(intent);
-        Log.i(TAG, "cleanup: intent:" + intent + " transportIntent:" + transportIntent);
-
-        IntermediateEncryptingTransport transport;
-        synchronized (mTransportsLock) {
-            transport = mTransports.remove(transportIntent.getComponent());
-        }
-        if (transport != null) {
-            mTransportClientManager.disposeOfTransportClient(transport.getClient(), CALLER);
-        } else {
-            Log.i(TAG, "Could not find IntermediateEncryptingTransport");
-        }
-    }
-}
diff --git a/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManagerTest.java b/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManagerTest.java
deleted file mode 100644
index 0d43a19..0000000
--- a/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManagerTest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.backup.encryption.transport;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNotSame;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.argThat;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import android.content.ComponentName;
-import android.content.Intent;
-import android.os.Bundle;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.server.backup.transport.TransportClient;
-import com.android.server.backup.transport.TransportClientManager;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class IntermediateEncryptingTransportManagerTest {
-    @Mock private TransportClient mTransportClient;
-    @Mock private TransportClientManager mTransportClientManager;
-
-    private final ComponentName mTransportComponent = new ComponentName("pkg", "class");
-    private final Bundle mExtras = new Bundle();
-    private Intent mEncryptingTransportIntent;
-    private IntermediateEncryptingTransportManager mIntermediateEncryptingTransportManager;
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        mExtras.putInt("test", 1);
-        mEncryptingTransportIntent =
-                TransportClientManager.getEncryptingTransportIntent(mTransportComponent)
-                        .putExtras(mExtras);
-        mIntermediateEncryptingTransportManager =
-                new IntermediateEncryptingTransportManager(mTransportClientManager);
-    }
-
-    @Test
-    public void testGet_createsClientWithRealTransportComponentAndExtras() {
-        when(mTransportClientManager.getTransportClient(any(), any(), any()))
-                .thenReturn(mTransportClient);
-
-        IntermediateEncryptingTransport intermediateEncryptingTransport =
-                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
-
-        assertEquals(mTransportClient, intermediateEncryptingTransport.getClient());
-        verify(mTransportClientManager, times(1))
-                .getTransportClient(eq(mTransportComponent), argThat(mExtras::kindofEquals), any());
-        verifyNoMoreInteractions(mTransportClientManager);
-    }
-
-    @Test
-    public void testGet_callTwice_returnsSameTransport() {
-        IntermediateEncryptingTransport transport1 =
-                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
-        IntermediateEncryptingTransport transport2 =
-                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
-
-        assertEquals(transport1, transport2);
-    }
-
-    @Test
-    public void testCleanup_disposesTransportClient() {
-        when(mTransportClientManager.getTransportClient(any(), any(), any()))
-                .thenReturn(mTransportClient);
-
-        IntermediateEncryptingTransport transport =
-                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
-        mIntermediateEncryptingTransportManager.cleanup(mEncryptingTransportIntent);
-
-        verify(mTransportClientManager, times(1)).getTransportClient(any(), any(), any());
-        verify(mTransportClientManager, times(1))
-                .disposeOfTransportClient(eq(mTransportClient), any());
-        verifyNoMoreInteractions(mTransportClientManager);
-    }
-
-    @Test
-    public void testCleanup_removesCachedTransport() {
-        when(mTransportClientManager.getTransportClient(any(), any(), any()))
-                .thenReturn(mTransportClient);
-
-        IntermediateEncryptingTransport transport1 =
-                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
-        mIntermediateEncryptingTransportManager.cleanup(mEncryptingTransportIntent);
-        IntermediateEncryptingTransport transport2 =
-                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
-
-        assertNotSame(transport1, transport2);
-    }
-}
diff --git a/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportTest.java b/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportTest.java
deleted file mode 100644
index a85b2e4..0000000
--- a/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportTest.java
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.backup.encryption.transport;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-import android.app.backup.BackupTransport;
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.os.ParcelFileDescriptor;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.backup.IBackupTransport;
-import com.android.server.backup.encryption.KeyValueEncrypter;
-import com.android.server.backup.transport.TransportClient;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.io.File;
-
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class IntermediateEncryptingTransportTest {
-    private static final String TEST_PACKAGE_NAME = "test_package";
-
-    private IntermediateEncryptingTransport mIntermediateEncryptingTransport;
-    private final PackageInfo mTestPackage = new PackageInfo();
-
-    @Mock private IBackupTransport mRealTransport;
-    @Mock private TransportClient mTransportClient;
-    @Mock private ParcelFileDescriptor mParcelFileDescriptor;
-    @Mock private KeyValueEncrypter mKeyValueEncrypter;
-    @Mock private Context mContext;
-
-    @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
-
-    private File mTempFile;
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-
-        mIntermediateEncryptingTransport =
-                new IntermediateEncryptingTransport(
-                        mTransportClient, mContext, mKeyValueEncrypter, true);
-        mTestPackage.packageName = TEST_PACKAGE_NAME;
-        mTempFile = mTemporaryFolder.newFile();
-
-        when(mTransportClient.connect(anyString())).thenReturn(mRealTransport);
-        when(mRealTransport.getRestoreData(any())).thenReturn(BackupTransport.TRANSPORT_OK);
-    }
-
-    @Test
-    public void testGetDelegate_callsConnect() throws Exception {
-        IBackupTransport ret = mIntermediateEncryptingTransport.getDelegate();
-
-        assertEquals(mRealTransport, ret);
-        verify(mTransportClient, times(1)).connect(anyString());
-        verifyNoMoreInteractions(mTransportClient);
-    }
-
-    @Test
-    public void testGetDelegate_callTwice_callsConnectOnce() throws Exception {
-        when(mTransportClient.connect(anyString())).thenReturn(mRealTransport);
-
-        IBackupTransport ret1 = mIntermediateEncryptingTransport.getDelegate();
-        IBackupTransport ret2 = mIntermediateEncryptingTransport.getDelegate();
-
-        assertEquals(mRealTransport, ret1);
-        assertEquals(mRealTransport, ret2);
-        verify(mTransportClient, times(1)).connect(anyString());
-        verifyNoMoreInteractions(mTransportClient);
-    }
-
-    @Test
-    public void testPerformBackup_shouldEncryptTrue_encryptsDataAndPassesToDelegate()
-            throws Exception {
-        mIntermediateEncryptingTransport =
-                new TestIntermediateTransport(mTransportClient, mContext, mKeyValueEncrypter, true);
-
-        mIntermediateEncryptingTransport.performBackup(mTestPackage, mParcelFileDescriptor, 0);
-
-        verify(mKeyValueEncrypter, times(1))
-                .encryptKeyValueData(eq(TEST_PACKAGE_NAME), eq(mParcelFileDescriptor), any());
-        verify(mRealTransport, times(1)).performBackup(eq(mTestPackage), any(), eq(0));
-    }
-
-    @Test
-    public void testPerformBackup_shouldEncryptFalse_doesntEncryptDataAndPassedToDelegate()
-            throws Exception {
-        mIntermediateEncryptingTransport =
-                new TestIntermediateTransport(
-                        mTransportClient, mContext, mKeyValueEncrypter, false);
-
-        mIntermediateEncryptingTransport.performBackup(mTestPackage, mParcelFileDescriptor, 0);
-
-        verifyZeroInteractions(mKeyValueEncrypter);
-        verify(mRealTransport, times(1))
-                .performBackup(eq(mTestPackage), eq(mParcelFileDescriptor), eq(0));
-    }
-
-    @Test
-    public void testGetRestoreData_shouldEncryptTrue_decryptsDataAndPassesToDelegate()
-            throws Exception {
-        mIntermediateEncryptingTransport =
-                new TestIntermediateTransport(mTransportClient, mContext, mKeyValueEncrypter, true);
-        mIntermediateEncryptingTransport.setNextRestorePackage(TEST_PACKAGE_NAME);
-
-        mIntermediateEncryptingTransport.getRestoreData(mParcelFileDescriptor);
-
-        verify(mKeyValueEncrypter, times(1))
-                .decryptKeyValueData(eq(TEST_PACKAGE_NAME), any(), eq(mParcelFileDescriptor));
-        verify(mRealTransport, times(1)).getRestoreData(any());
-    }
-
-    @Test
-    public void testGetRestoreData_shouldEncryptFalse_doesntDecryptDataAndPassesToDelegate()
-            throws Exception {
-        mIntermediateEncryptingTransport =
-                new TestIntermediateTransport(
-                        mTransportClient, mContext, mKeyValueEncrypter, false);
-        mIntermediateEncryptingTransport.setNextRestorePackage(TEST_PACKAGE_NAME);
-
-        mIntermediateEncryptingTransport.getRestoreData(mParcelFileDescriptor);
-
-        verifyZeroInteractions(mKeyValueEncrypter);
-        verify(mRealTransport, times(1)).getRestoreData(eq(mParcelFileDescriptor));
-    }
-
-    private final class TestIntermediateTransport extends IntermediateEncryptingTransport {
-        TestIntermediateTransport(
-                TransportClient transportClient,
-                Context context,
-                KeyValueEncrypter keyValueEncrypter,
-                boolean shouldEncrypt) {
-            super(transportClient, context, keyValueEncrypter, shouldEncrypt);
-        }
-
-        @Override
-        protected File getBackupTempStorage(String packageName) {
-            return mTempFile;
-        }
-
-        @Override
-        protected File getRestoreTempStorage(String packageName) {
-            return mTempFile;
-        }
-    }
-}
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
index 9f07317..126b823 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
@@ -42,8 +42,8 @@
 import android.companion.BluetoothDeviceFilter;
 import android.companion.BluetoothLeDeviceFilter;
 import android.companion.DeviceFilter;
+import android.companion.IAssociationRequestCallback;
 import android.companion.ICompanionDeviceDiscoveryService;
-import android.companion.IFindDeviceCallback;
 import android.companion.WifiDeviceFilter;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -92,7 +92,7 @@
     AssociationRequest mRequest;
     List<DeviceFilterPair> mDevicesFound;
     DeviceFilterPair mSelectedDevice;
-    IFindDeviceCallback mFindCallback;
+    IAssociationRequestCallback mApplicationCallback;
 
     AndroidFuture<String> mServiceCallback;
     boolean mIsScanning = false;
@@ -104,13 +104,13 @@
         @Override
         public void startDiscovery(AssociationRequest request,
                 String callingPackage,
-                IFindDeviceCallback findCallback,
+                IAssociationRequestCallback appCallback,
                 AndroidFuture<String> serviceCallback) {
             Log.i(LOG_TAG,
                     "startDiscovery() called with: filter = [" + request
-                            + "], findCallback = [" + findCallback + "]"
+                            + "], appCallback = [" + appCallback + "]"
                             + "], serviceCallback = [" + serviceCallback + "]");
-            mFindCallback = findCallback;
+            mApplicationCallback = appCallback;
             mServiceCallback = serviceCallback;
             Handler.getMain().sendMessage(obtainMessage(
                     CompanionDeviceDiscoveryService::startDiscovery,
@@ -299,7 +299,7 @@
     //TODO also, on timeout -> call onFailure
     private void onReadyToShowUI() {
         try {
-            mFindCallback.onSuccess(PendingIntent.getActivity(
+            mApplicationCallback.onAssociationPending(PendingIntent.getActivity(
                     this, 0,
                     new Intent(this, CompanionDeviceActivity.class),
                     PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_CANCEL_CURRENT
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 801b490..a3eb0ecc 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -251,7 +251,7 @@
             if (volume.getType() == VolumeInfo.TYPE_PUBLIC) {
                 root.flags |= Root.FLAG_HAS_SETTINGS;
             }
-            if (volume.isVisibleForRead(userId)) {
+            if (volume.isVisibleForUser(userId)) {
                 root.visiblePath = volume.getPathForUser(userId);
             } else {
                 root.visiblePath = null;
diff --git a/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp b/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
index 7ff9ced..b2c82c6 100644
--- a/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
+++ b/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
@@ -30,11 +30,8 @@
     char* writeBuffer = static_cast<char*>(buffer);
     size_t remainingBytes = byteCount;
     while (remainingBytes > 0) {
-        ssize_t writtenByteCount = write(fd, writeBuffer, remainingBytes);
+        ssize_t writtenByteCount = TEMP_FAILURE_RETRY(write(fd, writeBuffer, remainingBytes));
         if (writtenByteCount == -1) {
-            if (errno == EINTR) {
-                continue;
-            }
             __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
                     "Error writing to buffer: %d", errno);
             return false;
@@ -49,19 +46,17 @@
     char* readBuffer = static_cast<char*>(buffer);
     size_t remainingBytes = byteCount;
     while (remainingBytes > 0) {
-        ssize_t readByteCount = read(fd, readBuffer, remainingBytes);
+        ssize_t readByteCount = TEMP_FAILURE_RETRY(read(fd, readBuffer, remainingBytes));
+        if (readByteCount == -1) {
+            __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
+                    "Error reading from buffer: %d", errno);
+            return false;
+        }
 
         remainingBytes -= readByteCount;
         readBuffer += readByteCount;
 
-        if (readByteCount == -1) {
-            if (errno == EINTR) {
-                continue;
-            }
-            __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
-                    "Error reading from buffer: %d", errno);
-            return false;
-        } else if (readByteCount == 0 && remainingBytes > 0) {
+        if (readByteCount == 0 && remainingBytes > 0) {
             __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
                     "File closed before all bytes were read. %zu/%zu remaining", remainingBytes,
                     byteCount);
diff --git a/packages/SettingsLib/TopIntroPreference/Android.bp b/packages/SettingsLib/TopIntroPreference/Android.bp
index 9577281..cd0bdea 100644
--- a/packages/SettingsLib/TopIntroPreference/Android.bp
+++ b/packages/SettingsLib/TopIntroPreference/Android.bp
@@ -19,4 +19,8 @@
     ],
     sdk_version: "system_current",
     min_sdk_version: "21",
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.cellbroadcast",
+    ],
 }
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index f28d062..bd687e4 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -489,7 +489,7 @@
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
     <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carga rápida"</string>
     <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carga lenta"</string>
-    <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Cargando sin cables"</string>
+    <string name="battery_info_status_charging_wireless" msgid="8924722966861282197">"Carga inalámbrica"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"No se está cargando"</string>
     <string name="battery_info_status_not_charging" msgid="3371084153747234837">"Conectado pero sin cargar"</string>
     <string name="battery_info_status_full" msgid="1339002294876531312">"Cargada"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 73fadf7..ebaf4b1 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -266,7 +266,7 @@
     <string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"Veuillez vous connecter à un réseau Wi-Fi"</string>
     <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, débogage, développeur"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Raccourci de rapport de bogue"</string>
-    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afficher un bouton permettant d\'établir un rapport de bogue dans le menu de démarrage"</string>
+    <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afficher un bouton permettant d\'établir un rapport de bogue dans le menu de l\'interrupteur"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Rester activé"</string>
     <string name="keep_screen_on_summary" msgid="1510731514101925829">"L\'écran ne se met jamais en veille lors du chargement"</string>
     <string name="bt_hci_snoop_log" msgid="7291287955649081448">"Activer le journal HCI Snoop Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 173588b..0a96f59 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -527,8 +527,8 @@
     <string name="status_unavailable" msgid="5279036186589861608">"Non disponibile"</string>
     <string name="wifi_status_mac_randomized" msgid="466382542497832189">"Selezione casuale dell\'indirizzo MAC"</string>
     <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
+      <item quantity="one">%1$d devices connected</item>
       <item quantity="other">%1$d dispositivi connessi</item>
-      <item quantity="one">%1$d dispositivo connesso</item>
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Più tempo."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Meno tempo."</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index ebe5753..5a0ec2e 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -527,8 +527,8 @@
     <string name="status_unavailable" msgid="5279036186589861608">"Indisponível"</string>
     <string name="wifi_status_mac_randomized" msgid="466382542497832189">"O MAC é aleatório."</string>
     <plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
-      <item quantity="other">%1$d dispositivos ligados</item>
       <item quantity="one">%1$d dispositivo ligado</item>
+      <item quantity="other">%1$d dispositivos ligados</item>
     </plurals>
     <string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Mais tempo."</string>
     <string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Menos tempo."</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java
index b8ad321..0b436a9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothDeviceFilter.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.bluetooth;
 
+import android.annotation.SuppressLint;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothUuid;
@@ -118,8 +119,8 @@
                     return true;
                 }
             } else if (btClass != null) {
-                if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP) ||
-                        btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
+                if (doesClassMatch(btClass, BluetoothClass.PROFILE_A2DP)
+                        || doesClassMatch(btClass, BluetoothClass.PROFILE_HEADSET)) {
                     return true;
                 }
             }
@@ -137,7 +138,7 @@
                 }
             }
             return btClass != null
-                    && btClass.doesClassMatch(BluetoothClass.PROFILE_OPP);
+                    && doesClassMatch(btClass, BluetoothClass.PROFILE_OPP);
         }
     }
 
@@ -151,7 +152,7 @@
                 }
             }
             return btClass != null
-                    && btClass.doesClassMatch(BluetoothClass.PROFILE_PANU);
+                    && doesClassMatch(btClass, BluetoothClass.PROFILE_PANU);
         }
     }
 
@@ -165,7 +166,12 @@
                 }
             }
             return btClass != null
-                    && btClass.doesClassMatch(BluetoothClass.PROFILE_NAP);
+                    && doesClassMatch(btClass, BluetoothClass.PROFILE_NAP);
         }
     }
+
+    @SuppressLint("NewApi") // Hidden API made public
+    private static boolean doesClassMatch(BluetoothClass btClass, int classId) {
+        return btClass.doesClassMatch(classId);
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
index 58d2185..389892e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java
@@ -160,10 +160,12 @@
     private void registerIntentReceiver(BroadcastReceiver receiver, IntentFilter filter) {
         if (mUserHandle == null) {
             // If userHandle has not been provided, simply call registerReceiver.
-            mContext.registerReceiver(receiver, filter, null, mReceiverHandler);
+            mContext.registerReceiver(receiver, filter, null, mReceiverHandler,
+                    Context.RECEIVER_EXPORTED);
         } else {
             // userHandle was explicitly specified, so need to call multi-user aware API.
-            mContext.registerReceiverAsUser(receiver, mUserHandle, filter, null, mReceiverHandler);
+            mContext.registerReceiverAsUser(receiver, mUserHandle, filter, null, mReceiverHandler,
+                    Context.RECEIVER_EXPORTED);
         }
     }
 
@@ -305,7 +307,8 @@
             CachedBluetoothDevice cachedDevice = mDeviceManager.findDevice(device);
             if (cachedDevice == null) {
                 cachedDevice = mDeviceManager.addDevice(device);
-                Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice");
+                Log.d(TAG, "DeviceFoundHandler created new CachedBluetoothDevice "
+                        + cachedDevice.getDevice().getAnonymizedAddress());
             } else if (cachedDevice.getBondState() == BluetoothDevice.BOND_BONDED
                     && !cachedDevice.getDevice().isConnected()) {
                 // Dispatch device add callback to show bonded but
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
index 253629c..c9af4d5 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothUtils.java
@@ -2,6 +2,7 @@
 
 import static com.android.settingslib.widget.AdaptiveOutlineDrawable.ICON_TYPE_ADVANCED;
 
+import android.annotation.SuppressLint;
 import android.bluetooth.BluetoothClass;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
@@ -70,6 +71,12 @@
         void onShowError(Context context, String name, int messageResId);
     }
 
+    /**
+     * @param context to access resources from
+     * @param cachedDevice to get class from
+     * @return pair containing the drawable and the description of the Bluetooth class
+     *         of the device.
+     */
     public static Pair<Drawable, String> getBtClassDrawableWithDescription(Context context,
             CachedBluetoothDevice cachedDevice) {
         BluetoothClass btClass = cachedDevice.getBtClass();
@@ -110,13 +117,13 @@
             }
         }
         if (btClass != null) {
-            if (btClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
+            if (doesClassMatch(btClass, BluetoothClass.PROFILE_HEADSET)) {
                 return new Pair<>(
                         getBluetoothDrawable(context,
                                 com.android.internal.R.drawable.ic_bt_headset_hfp),
                         context.getString(R.string.bluetooth_talkback_headset));
             }
-            if (btClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
+            if (doesClassMatch(btClass, BluetoothClass.PROFILE_A2DP)) {
                 return new Pair<>(
                         getBluetoothDrawable(context,
                                 com.android.internal.R.drawable.ic_bt_headphones_a2dp),
@@ -376,4 +383,9 @@
         }
         return Uri.parse(data);
     }
+
+    @SuppressLint("NewApi") // Hidden API made public
+    private static boolean doesClassMatch(BluetoothClass btClass, int classId) {
+        return btClass.doesClassMatch(classId);
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index 912b468..a901160 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -194,7 +194,7 @@
     void onProfileStateChanged(LocalBluetoothProfile profile, int newProfileState) {
         if (BluetoothUtils.D) {
             Log.d(TAG, "onProfileStateChanged: profile " + profile + ", device "
-                    + mDevice.getAlias() + ", newProfileState " + newProfileState);
+                    + mDevice.getAnonymizedAddress() + ", newProfileState " + newProfileState);
         }
         if (mLocalAdapter.getState() == BluetoothAdapter.STATE_TURNING_OFF)
         {
@@ -745,7 +745,7 @@
         }
 
         if (BluetoothUtils.D) {
-            Log.d(TAG, "updating profiles for " + mDevice.getAlias());
+            Log.d(TAG, "updating profiles for " + mDevice.getAnonymizedAddress());
             BluetoothClass bluetoothClass = mDevice.getBluetoothClass();
 
             if (bluetoothClass != null) Log.v(TAG, "Class: " + bluetoothClass.toString());
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
index 80b03a4..e7a6b32 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothAdapter.java
@@ -19,11 +19,13 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.BluetoothProfile;
+import android.bluetooth.BluetoothStatusCodes;
 import android.bluetooth.le.BluetoothLeScanner;
 import android.content.Context;
 import android.os.ParcelUuid;
 import android.util.Log;
 
+import java.time.Duration;
 import java.util.List;
 import java.util.Set;
 
@@ -140,7 +142,7 @@
     }
 
     public void setDiscoverableTimeout(int timeout) {
-        mAdapter.setDiscoverableTimeout(timeout);
+        mAdapter.setDiscoverableTimeout(Duration.ofSeconds(timeout));
     }
 
     public long getDiscoveryEndMillis() {
@@ -156,7 +158,9 @@
     }
 
     public boolean setScanMode(int mode, int duration) {
-        return mAdapter.setScanMode(mode, duration);
+        return (mAdapter.setDiscoverableTimeout(Duration.ofSeconds(duration))
+                == BluetoothStatusCodes.SUCCESS
+                && mAdapter.setScanMode(mode) == BluetoothStatusCodes.SUCCESS);
     }
 
     public void startScanning(boolean force) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 71bf9f6..a781a62 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -175,9 +175,12 @@
     public UserIconDrawable setBadgeIfManagedUser(Context context, int userId) {
         Drawable badge = null;
         if (userId != UserHandle.USER_NULL) {
-            boolean isManaged = context.getSystemService(DevicePolicyManager.class)
-                    .getProfileOwnerAsUser(userId) != null;
-            if (isManaged) {
+            DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
+            boolean isCorp =
+                    dpm.getProfileOwnerAsUser(userId) != null // has an owner
+                    && dpm.getProfileOwnerOrDeviceOwnerSupervisionComponent(UserHandle.of(userId))
+                            == null; // and has no supervisor
+            if (isCorp) {
                 badge = getDrawableForDisplayDensity(
                         context, com.android.internal.R.drawable.ic_corp_badge_case);
             }
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
index b3205d7..b56ae38 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/BatteryStatus.java
@@ -109,6 +109,15 @@
     }
 
     /**
+     * Determine whether the device is plugged in wireless.
+     *
+     * @return true if the device is plugged in wireless
+     */
+    public boolean isPluggedInWireless() {
+        return plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
+    }
+
+    /**
      * Whether or not the device is charged. Note that some devices never return 100% for
      * battery level, so this allows either battery level or status to determine if the
      * battery is charged.
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
index 9d4669a..cd5c78d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/BluetoothMediaDevice.java
@@ -62,7 +62,7 @@
         if (!(drawable instanceof BitmapDrawable)) {
             setColorFilter(drawable);
         }
-        return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
+        return drawable;
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
index 949b245..c34f65c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaDevice.java
@@ -29,7 +29,6 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.settingslib.R;
-import com.android.settingslib.bluetooth.BluetoothUtils;
 
 import java.util.List;
 
@@ -61,7 +60,7 @@
     public Drawable getIcon() {
         final Drawable drawable = getIconWithoutBackground();
         setColorFilter(drawable);
-        return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
+        return drawable;
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
index b6c0b30..1139d33 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/PhoneMediaDevice.java
@@ -32,7 +32,6 @@
 import androidx.annotation.VisibleForTesting;
 
 import com.android.settingslib.R;
-import com.android.settingslib.bluetooth.BluetoothUtils;
 
 /**
  * PhoneMediaDevice extends MediaDevice to represents Phone device.
@@ -87,7 +86,7 @@
     public Drawable getIcon() {
         final Drawable drawable = getIconWithoutBackground();
         setColorFilter(drawable);
-        return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
+        return drawable;
     }
 
     @Override
diff --git a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
index 14a7cfa..5e91a14 100644
--- a/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
+++ b/packages/SettingsLib/src/com/android/settingslib/mobile/MobileMappings.java
@@ -113,6 +113,8 @@
                     TelephonyIcons.UNKNOWN);
             networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE),
                     TelephonyIcons.E);
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_GPRS),
+                    TelephonyIcons.G);
             networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA),
                     TelephonyIcons.ONE_X);
             networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT),
@@ -122,6 +124,8 @@
                     TelephonyIcons.THREE_G);
             networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_EDGE),
                     TelephonyIcons.THREE_G);
+            networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_GPRS),
+                    TelephonyIcons.THREE_G);
             networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_CDMA),
                     TelephonyIcons.THREE_G);
             networkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_1xRTT),
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index a210e90..8b17be1 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -19,7 +19,6 @@
 import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.AlertDialog;
-import android.app.Dialog;
 import android.app.NotificationManager;
 import android.content.Context;
 import android.content.DialogInterface;
@@ -85,6 +84,7 @@
 
     @VisibleForTesting
     protected Context mContext;
+    private final int mThemeResId;
     @VisibleForTesting
     protected TextView mZenAlarmWarning;
     @VisibleForTesting
@@ -97,10 +97,15 @@
     protected LayoutInflater mLayoutInflater;
 
     public EnableZenModeDialog(Context context) {
-        mContext = context;
+        this(context, 0);
     }
 
-    public Dialog createDialog() {
+    public EnableZenModeDialog(Context context, int themeResId) {
+        mContext = context;
+        mThemeResId = themeResId;
+    }
+
+    public AlertDialog createDialog() {
         mNotificationManager = (NotificationManager) mContext.
                 getSystemService(Context.NOTIFICATION_SERVICE);
         mForeverId =  Condition.newId(mContext).appendPath("forever").build();
@@ -108,7 +113,7 @@
         mUserId = mContext.getUserId();
         mAttached = false;
 
-        final AlertDialog.Builder builder = new AlertDialog.Builder(mContext)
+        final AlertDialog.Builder builder = new AlertDialog.Builder(mContext, mThemeResId)
                 .setTitle(R.string.zen_mode_settings_turn_on_dialog_title)
                 .setNegativeButton(R.string.cancel, null)
                 .setPositiveButton(R.string.zen_mode_enable_dialog_turn_on,
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
index 6f42d59..a50d4ae1 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/GlobalSettings.java
@@ -40,9 +40,6 @@
     public static final String[] SETTINGS_TO_BACKUP = {
         Settings.Global.APPLY_RAMPING_RINGER,
         Settings.Global.BUGREPORT_IN_POWER_MENU,
-        Settings.Global.CLOCKWORK_SYSUI_PACKAGE_NAME,
-        Settings.Global.CLOCKWORK_SYSUI_MAIN_ACTIVITY_NAME,
-        Settings.Global.CLOCKWORK_HOME_READY,
         Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
         Settings.Global.APP_AUTO_RESTRICTION_ENABLED,
         Settings.Global.AUTO_TIME,
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 1c7c19f..4e2111c 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -193,5 +193,6 @@
         Settings.Secure.LOCKSCREEN_SHOW_CONTROLS,
         Settings.Secure.LOCKSCREEN_SHOW_WALLET,
         Settings.Secure.LOCK_SCREEN_SHOW_QR_CODE_SCANNER,
+        Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK,
     };
 }
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
index 0fe4efe..71accc4 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java
@@ -47,6 +47,7 @@
         Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ,
         Settings.System.SCREEN_BRIGHTNESS_FOR_VR,
         Settings.System.ADAPTIVE_SLEEP,             // moved to secure
+        Settings.System.APPLY_RAMPING_RINGER,
         Settings.System.VIBRATE_INPUT_DEVICES,
         Settings.System.MODE_RINGER_STREAMS_AFFECTED,
         Settings.System.TEXT_AUTO_REPLACE,
@@ -80,6 +81,7 @@
         Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
         Settings.System.RING_VIBRATION_INTENSITY,
         Settings.System.HAPTIC_FEEDBACK_INTENSITY,
+        Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY,
         Settings.System.DISPLAY_COLOR_MODE_VENDOR_HINT, // must precede DISPLAY_COLOR_MODE
         Settings.System.DISPLAY_COLOR_MODE,
         Settings.System.ALARM_ALERT,
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 2bd5bdc..a10b819 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -116,8 +116,6 @@
         VALIDATORS.put(
                 Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD, PERCENTAGE_INTEGER_VALIDATOR);
         VALIDATORS.put(Global.BLUETOOTH_ON, BOOLEAN_VALIDATOR);
-        VALIDATORS.put(Global.CLOCKWORK_SYSUI_MAIN_ACTIVITY_NAME, ANY_STRING_VALIDATOR);
-        VALIDATORS.put(Global.CLOCKWORK_SYSUI_PACKAGE_NAME, ANY_STRING_VALIDATOR);
         VALIDATORS.put(Global.CLOCKWORK_HOME_READY, ANY_STRING_VALIDATOR);
         VALIDATORS.put(Global.ENABLE_TARE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.ENABLE_TARE_ALARM_MANAGER, BOOLEAN_VALIDATOR);
@@ -264,7 +262,6 @@
         VALIDATORS.put(Global.Wearable.AMBIENT_TOUCH_TO_WAKE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.Wearable.DECOMPOSABLE_WATCHFACE, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.Wearable.AMBIENT_FORCE_WHEN_DOCKED, BOOLEAN_VALIDATOR);
-        VALIDATORS.put(Global.Wearable.AMBIENT_GESTURE_SENSOR_ID, ANY_INTEGER_VALIDATOR);
         VALIDATORS.put(Global.Wearable.AMBIENT_LOW_BIT_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Global.Wearable.AMBIENT_PLUGGED_TIMEOUT_MIN, ANY_INTEGER_VALIDATOR);
         VALIDATORS.put(Global.Wearable.AMBIENT_TILT_TO_BRIGHT, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index 3a5ead3..dd1cb6b 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -154,6 +154,7 @@
         VALIDATORS.put(Secure.LOCKSCREEN_SHOW_CONTROLS, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.LOCKSCREEN_SHOW_WALLET, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.LOCK_SCREEN_SHOW_QR_CODE_SCANNER, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.DOZE_ENABLED, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.DOZE_ALWAYS_ON, BOOLEAN_VALIDATOR);
         VALIDATORS.put(Secure.DOZE_PICK_UP_GESTURE, BOOLEAN_VALIDATOR);
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
index 462c3a5..84e9d28 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java
@@ -117,9 +117,11 @@
         VALIDATORS.put(System.MODE_RINGER_STREAMS_AFFECTED, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(System.MUTE_STREAMS_AFFECTED, NON_NEGATIVE_INTEGER_VALIDATOR);
         VALIDATORS.put(System.VIBRATE_ON, BOOLEAN_VALIDATOR);
+        VALIDATORS.put(System.APPLY_RAMPING_RINGER, BOOLEAN_VALIDATOR);
         VALIDATORS.put(System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
         VALIDATORS.put(System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
         VALIDATORS.put(System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
+        VALIDATORS.put(System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_VALIDATOR);
         VALIDATORS.put(System.RINGTONE, URI_VALIDATOR);
         VALIDATORS.put(System.NOTIFICATION_SOUND, URI_VALIDATOR);
         VALIDATORS.put(System.ALARM_ALERT, URI_VALIDATOR);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 8c669d2..01ef34b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -284,10 +284,9 @@
         // versionCode of com.android.providers.settings corresponds to SDK_INT
         mRestoredFromSdkInt = (int) appVersionCode;
 
-        HashSet<String> movedToGlobal = new HashSet<String>();
-        Settings.System.getMovedToGlobalSettings(movedToGlobal);
-        Settings.Secure.getMovedToGlobalSettings(movedToGlobal);
+        Set<String> movedToGlobal = getMovedToGlobalSettings();
         Set<String> movedToSecure = getMovedToSecureSettings();
+        Set<String> movedToSystem = getMovedToSystemSettings();
 
         Set<String> preservedGlobalSettings = getSettingsToPreserveInRestore(
                 Settings.Global.CONTENT_URI);
@@ -318,32 +317,23 @@
             switch (key) {
                 case KEY_SYSTEM :
                     restoreSettings(data, Settings.System.CONTENT_URI, movedToGlobal,
-                            movedToSecure, R.array.restore_blocked_system_settings,
-                            dynamicBlockList,
+                            movedToSecure, /* movedToSystem= */ null,
+                            R.array.restore_blocked_system_settings, dynamicBlockList,
                             preservedSystemSettings);
                     mSettingsHelper.applyAudioSettings();
                     break;
 
                 case KEY_SECURE :
-                    restoreSettings(
-                            data,
-                            Settings.Secure.CONTENT_URI,
-                            movedToGlobal,
-                            null,
-                            R.array.restore_blocked_secure_settings,
-                            dynamicBlockList,
+                    restoreSettings(data, Settings.Secure.CONTENT_URI, movedToGlobal,
+                            /* movedToSecure= */ null, movedToSystem,
+                            R.array.restore_blocked_secure_settings, dynamicBlockList,
                             preservedSecureSettings);
                     break;
 
                 case KEY_GLOBAL :
-                    restoreSettings(
-                            data,
-                            Settings.Global.CONTENT_URI,
-                            null,
-                            movedToSecure,
-                            R.array.restore_blocked_global_settings,
-                            dynamicBlockList,
-                            preservedGlobalSettings);
+                    restoreSettings(data, Settings.Global.CONTENT_URI, /* movedToGlobal= */ null,
+                            movedToSecure, movedToSystem, R.array.restore_blocked_global_settings,
+                            dynamicBlockList, preservedGlobalSettings);
                     break;
 
                 case KEY_WIFI_SUPPLICANT :
@@ -435,10 +425,9 @@
         if (DEBUG_BACKUP) Log.d(TAG, "Flattened data version " + version);
         if (version <= FULL_BACKUP_VERSION) {
             // Generate the moved-to-global lookup table
-            HashSet<String> movedToGlobal = new HashSet<String>();
-            Settings.System.getMovedToGlobalSettings(movedToGlobal);
-            Settings.Secure.getMovedToGlobalSettings(movedToGlobal);
+            Set<String> movedToGlobal = getMovedToGlobalSettings();
             Set<String> movedToSecure = getMovedToSecureSettings();
+            Set<String> movedToSystem = getMovedToSystemSettings();
 
             // system settings data first
             int nBytes = in.readInt();
@@ -446,22 +435,19 @@
             byte[] buffer = new byte[nBytes];
             in.readFully(buffer, 0, nBytes);
             restoreSettings(buffer, nBytes, Settings.System.CONTENT_URI, movedToGlobal,
-                    movedToSecure, R.array.restore_blocked_system_settings,
-                    Collections.emptySet(), Collections.emptySet());
+                    movedToSecure, /* movedToSystem= */ null,
+                    R.array.restore_blocked_system_settings, Collections.emptySet(),
+                    Collections.emptySet());
 
             // secure settings
             nBytes = in.readInt();
             if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of secure settings data");
             if (nBytes > buffer.length) buffer = new byte[nBytes];
             in.readFully(buffer, 0, nBytes);
-            restoreSettings(
-                    buffer,
-                    nBytes,
-                    Settings.Secure.CONTENT_URI,
-                    movedToGlobal,
-                    null,
-                    R.array.restore_blocked_secure_settings,
-                    Collections.emptySet(), Collections.emptySet());
+            restoreSettings(buffer, nBytes, Settings.Secure.CONTENT_URI, movedToGlobal,
+                    /* movedToSecure= */ null, movedToSystem,
+                    R.array.restore_blocked_secure_settings, Collections.emptySet(),
+                    Collections.emptySet());
 
             // Global only if sufficiently new
             if (version >= FULL_BACKUP_ADDED_GLOBAL) {
@@ -469,10 +455,10 @@
                 if (DEBUG_BACKUP) Log.d(TAG, nBytes + " bytes of global settings data");
                 if (nBytes > buffer.length) buffer = new byte[nBytes];
                 in.readFully(buffer, 0, nBytes);
-                movedToGlobal.clear();  // no redirection; this *is* the global namespace
-                restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI, movedToGlobal,
-                        movedToSecure, R.array.restore_blocked_global_settings,
-                        Collections.emptySet(), Collections.emptySet());
+                restoreSettings(buffer, nBytes, Settings.Global.CONTENT_URI,
+                        /* movedToGlobal= */ null, movedToSecure, movedToSystem,
+                        R.array.restore_blocked_global_settings, Collections.emptySet(),
+                        Collections.emptySet());
             }
 
             // locale
@@ -543,6 +529,13 @@
         }
     }
 
+    private Set<String> getMovedToGlobalSettings() {
+        HashSet<String> movedToGlobalSettings = new HashSet<String>();
+        Settings.System.getMovedToGlobalSettings(movedToGlobalSettings);
+        Settings.Secure.getMovedToGlobalSettings(movedToGlobalSettings);
+        return movedToGlobalSettings;
+    }
+
     private Set<String> getMovedToSecureSettings() {
         Set<String> movedToSecureSettings = new HashSet<>();
         Settings.Global.getMovedToSecureSettings(movedToSecureSettings);
@@ -550,6 +543,13 @@
         return movedToSecureSettings;
     }
 
+    private Set<String> getMovedToSystemSettings() {
+        Set<String> movedToSystemSettings = new HashSet<>();
+        Settings.Global.getMovedToSystemSettings(movedToSystemSettings);
+        Settings.Secure.getMovedToSystemSettings(movedToSystemSettings);
+        return movedToSystemSettings;
+    }
+
     private long[] readOldChecksums(ParcelFileDescriptor oldState) throws IOException {
         long[] stateChecksums = new long[STATE_SIZE];
 
@@ -710,8 +710,9 @@
     private void restoreSettings(
             BackupDataInput data,
             Uri contentUri,
-            HashSet<String> movedToGlobal,
+            Set<String> movedToGlobal,
             Set<String> movedToSecure,
+            Set<String> movedToSystem,
             int blockedSettingsArrayId,
             Set<String> dynamicBlockList,
             Set<String> settingsToPreserve) {
@@ -728,6 +729,7 @@
                 contentUri,
                 movedToGlobal,
                 movedToSecure,
+                movedToSystem,
                 blockedSettingsArrayId,
                 dynamicBlockList,
                 settingsToPreserve);
@@ -737,8 +739,9 @@
             byte[] settings,
             int bytes,
             Uri contentUri,
-            HashSet<String> movedToGlobal,
+            Set<String> movedToGlobal,
             Set<String> movedToSecure,
+            Set<String> movedToSystem,
             int blockedSettingsArrayId,
             Set<String> dynamicBlockList,
             Set<String> settingsToPreserve) {
@@ -749,6 +752,7 @@
                 contentUri,
                 movedToGlobal,
                 movedToSecure,
+                movedToSystem,
                 blockedSettingsArrayId,
                 dynamicBlockList,
                 settingsToPreserve);
@@ -760,8 +764,9 @@
             int pos,
             int bytes,
             Uri contentUri,
-            HashSet<String> movedToGlobal,
+            Set<String> movedToGlobal,
             Set<String> movedToSecure,
+            Set<String> movedToSystem,
             int blockedSettingsArrayId,
             Set<String> dynamicBlockList,
             Set<String> settingsToPreserve) {
@@ -842,6 +847,8 @@
                 destination = Settings.Global.CONTENT_URI;
             } else if (movedToSecure != null && movedToSecure.contains(key)) {
                 destination = Settings.Secure.CONTENT_URI;
+            } else if (movedToSystem != null && movedToSystem.contains(key)) {
+                destination = Settings.System.CONTENT_URI;
             } else {
                 destination = contentUri;
             }
@@ -1192,6 +1199,7 @@
                 Settings.Secure.CONTENT_URI,
                 null,
                 null,
+                null,
                 blockedSettingsArrayId,
                 dynamicBlocklist,
                 preservedSettings);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 5d75d4f..a67b565 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1620,7 +1620,11 @@
         p.end(token);
         // Please insert new settings using the same order as in GlobalSettingsProto.
 
+        // The rest of the settings were moved to Settings.Secure or Settings.System, and are thus
+        // excluded here since they're deprecated from Settings.Global.
+
         // Settings.Global.INSTALL_NON_MARKET_APPS intentionally excluded since it's deprecated.
+        // Settings.Global.APPLY_RAMPING_RINGER intentionally excluded since it's deprecated.
     }
 
     private static void dumpProtoConfigSettingsLocked(
@@ -2953,6 +2957,10 @@
                 Settings.System.WHEN_TO_MAKE_WIFI_CALLS,
                 SystemSettingsProto.WHEN_TO_MAKE_WIFI_CALLS);
 
+        dumpSetting(s, p,
+                Settings.System.APPLY_RAMPING_RINGER,
+                SystemSettingsProto.APPLY_RAMPING_RINGER);
+
         // Please insert new settings using the same order as in SecureSettingsProto.
 
         // The rest of the settings were moved to Settings.Secure, and are thus excluded here since
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index aca70f1..11e4916 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -289,6 +289,12 @@
         Settings.Global.getMovedToSecureSettings(sGlobalMovedToSecureSettings);
     }
 
+    // Per all users global settings that moved to the per user system settings.
+    static final Set<String> sGlobalMovedToSystemSettings = new ArraySet<>();
+    static {
+        Settings.Global.getMovedToSystemSettings(sGlobalMovedToSystemSettings);
+    }
+
     // Per user secure settings that are cloned for the managed profiles of the user.
     private static final Set<String> sSecureCloneToManagedSettings = new ArraySet<>();
     static {
@@ -2604,6 +2610,10 @@
                 if (sGlobalMovedToSecureSettings.contains(name)) {
                     table = TABLE_SECURE;
                 }
+
+                if (sGlobalMovedToSystemSettings.contains(name)) {
+                    table = TABLE_SYSTEM;
+                }
             }
 
             return table;
@@ -3594,7 +3604,7 @@
         }
 
         private final class UpgradeController {
-            private static final int SETTINGS_VERSION = 206;
+            private static final int SETTINGS_VERSION = 207;
 
             private final int mUserId;
 
@@ -4611,18 +4621,7 @@
 
                 if (currentVersion == 174) {
                     // Version 174: Set the default value for Global Settings: APPLY_RAMPING_RINGER
-
-                    final SettingsState globalSettings = getGlobalSettingsLocked();
-
-                    Setting currentRampingRingerSetting = globalSettings.getSettingLocked(
-                            Settings.Global.APPLY_RAMPING_RINGER);
-                    if (currentRampingRingerSetting.isNull()) {
-                        globalSettings.insertSettingOverrideableByRestoreLocked(
-                                Settings.Global.APPLY_RAMPING_RINGER,
-                                getContext().getResources().getBoolean(
-                                        R.bool.def_apply_ramping_ringer) ? "1" : "0", null,
-                                true, SettingsState.SYSTEM_PACKAGE_NAME);
-                    }
+                    // Removed. Moved APPLY_RAMPING_RINGER to System Settings, set in version 206.
 
                     currentVersion = 175;
                 }
@@ -5325,9 +5324,6 @@
                             Settings.Global.Wearable.AMBIENT_FORCE_WHEN_DOCKED,
                             SystemProperties.getBoolean("ro.ambient.force_when_docked", false));
                     initGlobalSettingsDefaultValForWearLocked(
-                            Settings.Global.Wearable.AMBIENT_GESTURE_SENSOR_ID,
-                            SystemProperties.getInt("ro.ambient.gesture_sensor_id", 0));
-                    initGlobalSettingsDefaultValForWearLocked(
                             Settings.Global.Wearable.AMBIENT_LOW_BIT_ENABLED,
                             SystemProperties.getBoolean("ro.ambient.low_bit_enabled", false));
                     initGlobalSettingsDefaultValForWearLocked(
@@ -5438,6 +5434,34 @@
                     currentVersion = 206;
                 }
 
+                if (currentVersion == 206) {
+                    // Version 206: APPLY_RAMPING_RINGER moved to System settings. Use the old value
+                    // for the newly inserted system setting and keep it to be restored to other
+                    // users. Set default value if global value is not set.
+                    final SettingsState systemSettings = getSystemSettingsLocked(userId);
+                    Setting globalValue = getGlobalSettingsLocked()
+                            .getSettingLocked(Global.APPLY_RAMPING_RINGER);
+                    Setting currentValue = systemSettings
+                            .getSettingLocked(Settings.System.APPLY_RAMPING_RINGER);
+                    if (currentValue.isNull()) {
+                        if (!globalValue.isNull()) {
+                            // Recover settings from Global.
+                            systemSettings.insertSettingOverrideableByRestoreLocked(
+                                    Settings.System.APPLY_RAMPING_RINGER, globalValue.getValue(),
+                                    globalValue.getTag(), globalValue.isDefaultFromSystem(),
+                                    SettingsState.SYSTEM_PACKAGE_NAME);
+                        } else {
+                            // Set default value.
+                            systemSettings.insertSettingOverrideableByRestoreLocked(
+                                    Settings.System.APPLY_RAMPING_RINGER,
+                                    getContext().getResources().getBoolean(
+                                            R.bool.def_apply_ramping_ringer) ? "1" : "0",
+                                    null /* tag */, true /* makeDefault */,
+                                    SettingsState.SYSTEM_PACKAGE_NAME);
+                        }
+                    }
+                    currentVersion = 207;
+                }
 
                 // vXXX: Add new settings above this point.
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 4aee164..aa6661b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -345,7 +345,6 @@
     }
 
     // The settings provider must hold its lock when calling here.
-    @GuardedBy("mLock")
     public Setting getSettingLocked(String name) {
         if (TextUtils.isEmpty(name)) {
             return mNullSetting;
@@ -385,7 +384,6 @@
     }
 
     // The settings provider must hold its lock when calling here.
-    @GuardedBy("mLock")
     public boolean insertSettingOverrideableByRestoreLocked(String name, String value, String tag,
             boolean makeDefault, String packageName) {
         return insertSettingLocked(name, value, tag, makeDefault, false, packageName,
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 53df2e82..c9c93c4 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -591,6 +591,7 @@
                     Settings.Global.CACHED_APPS_FREEZER_ENABLED,
                     Settings.Global.APP_INTEGRITY_VERIFICATION_TIMEOUT,
                     Settings.Global.KEY_CHORD_POWER_VOLUME_UP,
+                    Settings.Global.CLOCKWORK_HOME_READY,
                     Settings.Global.Wearable.BATTERY_SAVER_MODE,
                     Settings.Global.Wearable.COMBINED_LOCATION_ENABLED,
                     Settings.Global.Wearable.HAS_PAY_TOKENS,
@@ -639,7 +640,6 @@
                     Settings.Global.Wearable.AMBIENT_TILT_TO_BRIGHT,
                     Settings.Global.Wearable.DECOMPOSABLE_WATCHFACE,
                     Settings.Global.Wearable.AMBIENT_FORCE_WHEN_DOCKED,
-                    Settings.Global.Wearable.AMBIENT_GESTURE_SENSOR_ID,
                     Settings.Global.Wearable.AMBIENT_LOW_BIT_ENABLED,
                     Settings.Global.Wearable.AMBIENT_PLUGGED_TIMEOUT_MIN,
                     Settings.Global.Wearable.PAIRED_DEVICE_OS_TYPE,
diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
index f5334fb..433aac7 100644
--- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
+++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsBackupAgentTest.java
@@ -205,8 +205,8 @@
         mAgentUnderTest.mSettingsHelper = settingsHelper;
 
         byte[] backupData = generateBackupData(TEST_VALUES);
-        mAgentUnderTest.restoreSettings(backupData, /* pos */ 0, backupData.length, TEST_URI, new HashSet<>(),
-                Collections.emptySet(), /* blockedSettingsArrayId */ 0, Collections.emptySet(),
+        mAgentUnderTest.restoreSettings(backupData, /* pos */ 0, backupData.length, TEST_URI,
+                null, null, null, /* blockedSettingsArrayId */ 0, Collections.emptySet(),
                 new HashSet<>(Collections.singletonList(SettingsBackupAgent.getQualifiedKeyForSetting(PRESERVED_TEST_SETTING, TEST_URI))));
 
         assertTrue(settingsHelper.mWrittenValues.containsKey(OVERRIDDEN_TEST_SETTING));
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index f59f099..aefe3b7 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -90,7 +90,6 @@
     <uses-permission android:name="android.permission.RESTART_PACKAGES" />
     <uses-permission android:name="android.permission.REQUEST_COMPANION_RUN_IN_BACKGROUND" />
     <uses-permission android:name="android.permission.REQUEST_COMPANION_USE_DATA_IN_BACKGROUND" />
-    <uses-permission android:name="android.permission.REQUEST_COMPANION_PROFILE_WATCH" />
     <uses-permission android:name="android.permission.HIDE_OVERLAY_WINDOWS" />
     <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
     <uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
@@ -297,9 +296,13 @@
     <!-- Permission needed to wipe the device for Test Harness Mode -->
     <uses-permission android:name="android.permission.ENABLE_TEST_HARNESS_MODE" />
 
-    <!-- Permissions required to test CompanionDeviceManager teses in CTS -->
-    <uses-permission android:name="android.permission.MANAGE_COMPANION_DEVICES" />
+    <!-- Permission needed for CTS test - CompanionDeviceManagerTest -->
     <uses-permission android:name="android.permission.COMPANION_APPROVE_WIFI_CONNECTIONS" />
+    <uses-permission android:name="android.permission.MANAGE_COMPANION_DEVICES" />
+    <uses-permission android:name="android.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING" />
+    <uses-permission android:name="android.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION" />
+    <uses-permission android:name="android.permission.REQUEST_COMPANION_PROFILE_WATCH" />
+    <uses-permission android:name="android.permission.REQUEST_COMPANION_SELF_MANAGED" />
 
     <uses-permission android:name="android.permission.MANAGE_APPOPS" />
     <uses-permission android:name="android.permission.WATCH_APPOPS" />
@@ -589,6 +592,9 @@
     <!-- Permission required to run GtsAssistantTestCases -->
     <uses-permission android:name="android.permission.MANAGE_VOICE_KEYPHRASES" />
 
+    <!-- Permission required for CTS test - SettingsMultiPaneDeepLinkTest -->
+    <uses-permission android:name="android.permission.LAUNCH_MULTI_PANE_SETTINGS_DEEP_LINK" />
+
     <application android:label="@string/app_label"
                 android:theme="@android:style/Theme.DeviceDefault.DayNight"
                 android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 8c70112..ee9d430 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -150,6 +150,7 @@
     // Internal intents used on notification actions.
     static final String INTENT_BUGREPORT_CANCEL = "android.intent.action.BUGREPORT_CANCEL";
     static final String INTENT_BUGREPORT_SHARE = "android.intent.action.BUGREPORT_SHARE";
+    static final String INTENT_BUGREPORT_DONE = "android.intent.action.BUGREPORT_DONE";
     static final String INTENT_BUGREPORT_INFO_LAUNCH =
             "android.intent.action.BUGREPORT_INFO_LAUNCH";
     static final String INTENT_BUGREPORT_SCREENSHOT =
@@ -555,6 +556,8 @@
                 case INTENT_BUGREPORT_SHARE:
                     shareBugreport(id, (BugreportInfo) intent.getParcelableExtra(EXTRA_INFO));
                     break;
+                case INTENT_BUGREPORT_DONE:
+                    maybeShowWarningMessageAndCloseNotification(id);
                 case INTENT_BUGREPORT_CANCEL:
                     cancel(id);
                     break;
@@ -809,10 +812,30 @@
     }
 
     /**
+     * Creates a {@link PendingIntent} for a notification action used to show warning about the
+     * sensitivity of bugreport data and then close bugreport notification.
+     *
+     * Note that, the warning message may not be shown if the user has chosen not to see the
+     * message anymore.
+     */
+    private static PendingIntent newBugreportDoneIntent(Context context, BugreportInfo info) {
+        final Intent intent = new Intent(INTENT_BUGREPORT_DONE);
+        intent.setClass(context, BugreportProgressService.class);
+        intent.putExtra(EXTRA_ID, info.id);
+        return PendingIntent.getService(context, info.id, intent,
+                PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
+    }
+
+    @GuardedBy("mLock")
+    private void stopProgressLocked(int id) {
+        stopProgressLocked(id, /* cancelNotification */ true);
+    }
+
+    /**
      * Finalizes the progress on a given bugreport and cancel its notification.
      */
     @GuardedBy("mLock")
-    private void stopProgressLocked(int id) {
+    private void stopProgressLocked(int id, boolean cancelNotification) {
         if (mBugreportInfos.indexOfKey(id) < 0) {
             Log.w(TAG, "ID not watched: " + id);
         } else {
@@ -821,8 +844,13 @@
         }
         // Must stop foreground service first, otherwise notif.cancel() will fail below.
         stopForegroundWhenDoneLocked(id);
-        Log.d(TAG, "stopProgress(" + id + "): cancel notification");
-        NotificationManager.from(mContext).cancel(id);
+
+        if (cancelNotification) {
+            Log.d(TAG, "stopProgress(" + id + "): cancel notification");
+            NotificationManager.from(mContext).cancel(id);
+        } else {
+            Log.d(TAG, "stopProgress(" + id + ")");
+        }
         stopSelfWhenDoneLocked();
     }
 
@@ -1039,7 +1067,8 @@
     }
 
     /**
-     * Wraps up bugreport generation and triggers a notification to share the bugreport.
+     * Wraps up bugreport generation and triggers a notification to either share the bugreport or
+     * just notify the ending of the bugreport generation, according to the device type.
      */
     private void onBugreportFinished(BugreportInfo info) {
         if (!TextUtils.isEmpty(info.shareTitle)) {
@@ -1054,25 +1083,46 @@
             stopForegroundWhenDoneLocked(info.id);
         }
 
-        triggerLocalNotification(mContext, info);
-    }
-
-    /**
-     * Responsible for triggering a notification that allows the user to start a "share" intent with
-     * the bugreport. On watches we have other methods to allow the user to start this intent
-     * (usually by triggering it on another connected device); we don't need to display the
-     * notification in this case.
-     */
-    private void triggerLocalNotification(final Context context, final BugreportInfo info) {
         if (!info.bugreportFile.exists() || !info.bugreportFile.canRead()) {
             Log.e(TAG, "Could not read bugreport file " + info.bugreportFile);
-            Toast.makeText(context, R.string.bugreport_unreadable_text, Toast.LENGTH_LONG).show();
+            Toast.makeText(mContext, R.string.bugreport_unreadable_text, Toast.LENGTH_LONG).show();
             synchronized (mLock) {
                 stopProgressLocked(info.id);
             }
             return;
         }
 
+        if (mIsWatch) {
+            // Wear wants to send the notification directly and not wait for the user to tap on the
+            // notification.
+            triggerShareBugreportAndLocalNotification(info);
+        } else {
+            triggerLocalNotification(info);
+        }
+    }
+
+    /**
+     * Responsible for starting the bugerport sharing process and posting a notification which
+     * shows that the bugreport has been taken and that the sharing process has kicked-off.
+     */
+    private void triggerShareBugreportAndLocalNotification(final BugreportInfo info) {
+        boolean isPlainText = info.bugreportFile.getName().toLowerCase().endsWith(".txt");
+        if (!isPlainText) {
+            // Already zipped, share it right away.
+            shareBugreport(info.id, info, /* showWarning */ false,
+                /* cancelNotificationWhenStoppingProgress */ false);
+            sendBugreportNotification(info, mTakingScreenshot);
+        } else {
+            // Asynchronously zip the file first, then share it.
+            shareAndPostNotificationForZippedBugreport(info, mTakingScreenshot);
+        }
+    }
+
+    /**
+     * Responsible for triggering a notification that allows the user to start a "share" intent with
+     * the bugreport.
+     */
+    private void triggerLocalNotification(final BugreportInfo info) {
         boolean isPlainText = info.bugreportFile.getName().toLowerCase().endsWith(".txt");
         if (!isPlainText) {
             // Already zipped, send it right away.
@@ -1083,9 +1133,11 @@
         }
     }
 
-    private static Intent buildWarningIntent(Context context, Intent sendIntent) {
+    private static Intent buildWarningIntent(Context context, @Nullable Intent sendIntent) {
         final Intent intent = new Intent(context, BugreportWarningActivity.class);
-        intent.putExtra(Intent.EXTRA_INTENT, sendIntent);
+        if (sendIntent != null) {
+            intent.putExtra(Intent.EXTRA_INTENT, sendIntent);
+        }
         return intent;
     }
 
@@ -1163,11 +1215,30 @@
         return intent;
     }
 
+    private boolean hasUserDecidedNotToGetWarningMessage() {
+        return getWarningState(mContext, STATE_UNKNOWN) == STATE_HIDE;
+    }
+
+    private void maybeShowWarningMessageAndCloseNotification(int id) {
+        if (!hasUserDecidedNotToGetWarningMessage()) {
+            Intent warningIntent = buildWarningIntent(mContext, /* sendIntent */ null);
+            warningIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            mContext.startActivity(warningIntent);
+        }
+        NotificationManager.from(mContext).cancel(id);
+    }
+
+    private void shareBugreport(int id, BugreportInfo sharedInfo) {
+        shareBugreport(id, sharedInfo, !hasUserDecidedNotToGetWarningMessage(),
+            /* cancelNotificationWhenStoppingProgress */ true);
+    }
+
     /**
      * Shares the bugreport upon user's request by issuing a {@link Intent#ACTION_SEND_MULTIPLE}
      * intent, but issuing a warning dialog the first time.
      */
-    private void shareBugreport(int id, BugreportInfo sharedInfo) {
+    private void shareBugreport(int id, BugreportInfo sharedInfo, boolean showWarning,
+            boolean cancelNotificationWhenStoppingProgress) {
         MetricsLogger.action(this, MetricsEvent.ACTION_BUGREPORT_NOTIFICATION_ACTION_SHARE);
         BugreportInfo info;
         synchronized (mLock) {
@@ -1199,7 +1270,7 @@
         boolean useChooser = true;
 
         // Send through warning dialog by default
-        if (getWarningState(mContext, STATE_UNKNOWN) != STATE_HIDE) {
+        if (showWarning) {
             notifIntent = buildWarningIntent(mContext, sendIntent);
             // No need to show a chooser in this case.
             useChooser = false;
@@ -1216,7 +1287,7 @@
         }
         synchronized (mLock) {
             // ... and stop watching this process.
-            stopProgressLocked(id);
+            stopProgressLocked(id, cancelNotificationWhenStoppingProgress);
         }
     }
 
@@ -1240,12 +1311,6 @@
         // Since adding the details can take a while, do it before notifying user.
         addDetailsToZipFile(info);
 
-        final Intent shareIntent = new Intent(INTENT_BUGREPORT_SHARE);
-        shareIntent.setClass(mContext, BugreportProgressService.class);
-        shareIntent.setAction(INTENT_BUGREPORT_SHARE);
-        shareIntent.putExtra(EXTRA_ID, info.id);
-        shareIntent.putExtra(EXTRA_INFO, info);
-
         String content;
         content = takingScreenshot ?
                 mContext.getString(R.string.bugreport_finished_pending_screenshot_text)
@@ -1263,11 +1328,32 @@
         final Notification.Builder builder = newBaseNotification(mContext)
                 .setContentTitle(title)
                 .setTicker(title)
-                .setContentText(content)
-                .setContentIntent(PendingIntent.getService(mContext, info.id, shareIntent,
-                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
                 .setOnlyAlertOnce(false)
-                .setDeleteIntent(newCancelIntent(mContext, info));
+                .setContentText(content);
+
+        if (!mIsWatch) {
+            final Intent shareIntent = new Intent(INTENT_BUGREPORT_SHARE);
+            shareIntent.setClass(mContext, BugreportProgressService.class);
+            shareIntent.setAction(INTENT_BUGREPORT_SHARE);
+            shareIntent.putExtra(EXTRA_ID, info.id);
+            shareIntent.putExtra(EXTRA_INFO, info);
+
+            builder.setContentIntent(PendingIntent.getService(mContext, info.id, shareIntent,
+                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
+                    .setDeleteIntent(newCancelIntent(mContext, info));
+        } else {
+            // Device is a watch.
+            if (hasUserDecidedNotToGetWarningMessage()) {
+                // No action button needed for the notification. User can swipe to dimiss.
+                builder.setActions(new Action[0]);
+            } else {
+                // Add action button to lead user to the warning screen.
+                builder.setActions(
+                        new Action.Builder(
+                                null, mContext.getString(R.string.bugreport_info_action),
+                        newBugreportDoneIntent(mContext, info)).build());
+            }
+        }
 
         if (!TextUtils.isEmpty(info.getName())) {
             builder.setSubText(info.getName());
@@ -1327,6 +1413,24 @@
     }
 
     /**
+     * Zips a bugreport, shares it, and sends for it a bugreport notification.
+     */
+    private void shareAndPostNotificationForZippedBugreport(final BugreportInfo info,
+            final boolean takingScreenshot) {
+        new AsyncTask<Void, Void, Void>() {
+            @Override
+            protected Void doInBackground(Void... params) {
+                Looper.prepare();
+                zipBugreport(info);
+                shareBugreport(info.id, info, /* showWarning */ false,
+                /* cancelNotificationWhenStoppingProgress */ false);
+                sendBugreportNotification(info, mTakingScreenshot);
+                return null;
+            }
+        }.execute();
+    }
+
+    /**
      * Zips a bugreport file, returning the path to the new file (or to the
      * original in case of failure).
      */
diff --git a/packages/Shell/src/com/android/shell/BugreportWarningActivity.java b/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
index ecd1369..a44e236 100644
--- a/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
+++ b/packages/Shell/src/com/android/shell/BugreportWarningActivity.java
@@ -54,9 +54,11 @@
 
         mSendIntent = getIntent().getParcelableExtra(Intent.EXTRA_INTENT);
 
-        // We need to touch the extras to unpack them so they get migrated to
-        // ClipData correctly.
-        mSendIntent.hasExtra(Intent.EXTRA_STREAM);
+        if (mSendIntent != null) {
+            // We need to touch the extras to unpack them so they get migrated to
+            // ClipData correctly.
+            mSendIntent.hasExtra(Intent.EXTRA_STREAM);
+        }
 
         final AlertController.AlertParams ap = mAlertParams;
         ap.mView = LayoutInflater.from(this).inflate(R.layout.confirm_repeat, null);
@@ -84,7 +86,9 @@
         if (which == AlertDialog.BUTTON_POSITIVE) {
             // Remember confirm state, and launch target
             setWarningState(this, mConfirmRepeat.isChecked() ? STATE_HIDE : STATE_SHOW);
-            sendShareIntent(this, mSendIntent);
+            if (mSendIntent != null) {
+                sendShareIntent(this, mSendIntent);
+            }
         }
 
         finish();
diff --git a/packages/SystemUI/animation/res/values/ids.xml b/packages/SystemUI/animation/res/values/ids.xml
index ef60a24..c4cb89f 100644
--- a/packages/SystemUI/animation/res/values/ids.xml
+++ b/packages/SystemUI/animation/res/values/ids.xml
@@ -16,4 +16,5 @@
 -->
 <resources>
     <item type="id" name="launch_animation_running"/>
+    <item type="id" name="dialog_content_parent" />
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index 413612f..e5726b0 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -27,7 +27,6 @@
 import android.util.Log
 import android.util.MathUtils
 import android.view.GhostView
-import android.view.Gravity
 import android.view.View
 import android.view.ViewGroup
 import android.view.ViewTreeObserver.OnPreDrawListener
@@ -40,6 +39,7 @@
 import kotlin.math.roundToInt
 
 private const val TAG = "DialogLaunchAnimator"
+private val DIALOG_CONTENT_PARENT_ID = R.id.dialog_content_parent
 
 /**
  * A class that allows dialogs to be started in a seamless way from a view that is transforming
@@ -86,10 +86,11 @@
         // If the parent of the view we are launching from is the background of some other animated
         // dialog, then this means the caller intent is to launch a dialog from another dialog. In
         // this case, we also animate the parent (which is the dialog background).
-        val dialogContentParent = openedDialogs
-            .firstOrNull { it.dialogContentParent == view.parent }
-            ?.dialogContentParent
-        val animateFrom = dialogContentParent ?: view
+        val animatedParent = openedDialogs.firstOrNull {
+            it.dialogContentWithBackground == view || it.dialogContentWithBackground == view.parent
+        }
+        val dialogContentWithBackground = animatedParent?.dialogContentWithBackground
+        val animateFrom = dialogContentWithBackground ?: view
 
         // Make sure we don't run the launch animation from the same view twice at the same time.
         if (animateFrom.getTag(TAG_LAUNCH_ANIMATION_RUNNING) != null) {
@@ -100,12 +101,18 @@
 
         animateFrom.setTag(TAG_LAUNCH_ANIMATION_RUNNING, true)
 
-        val launchAnimation = AnimatedDialog(
-            context, launchAnimator, hostDialogProvider, animateFrom,
-            onDialogDismissed = { openedDialogs.remove(it) }, originalDialog = dialog,
-            animateBackgroundBoundsChange)
-        val hostDialog = launchAnimation.hostDialog
-        openedDialogs.add(launchAnimation)
+        val animatedDialog = AnimatedDialog(
+                context,
+                launchAnimator,
+                hostDialogProvider,
+                animateFrom,
+                onDialogDismissed = { openedDialogs.remove(it) },
+                originalDialog = dialog,
+                animateBackgroundBoundsChange,
+                animatedParent
+        )
+        val hostDialog = animatedDialog.hostDialog
+        openedDialogs.add(animatedDialog)
 
         // If the dialog is dismissed/hidden/shown, then we should actually dismiss/hide/show the
         // host dialog.
@@ -119,15 +126,15 @@
                     // If AOD is disabled the screen will directly becomes black and we won't see
                     // the animation anyways.
                     if (reason == DialogListener.DismissReason.DEVICE_LOCKED) {
-                        launchAnimation.exitAnimationDisabled = true
+                        animatedDialog.exitAnimationDisabled = true
                     }
 
                     hostDialog.dismiss()
                 }
 
                 override fun onHide() {
-                    if (launchAnimation.ignoreNextCallToHide) {
-                        launchAnimation.ignoreNextCallToHide = false
+                    if (animatedDialog.ignoreNextCallToHide) {
+                        animatedDialog.ignoreNextCallToHide = false
                         return
                     }
 
@@ -138,21 +145,44 @@
                     hostDialog.show()
 
                     // We don't actually want to show the original dialog, so hide it.
-                    launchAnimation.ignoreNextCallToHide = true
+                    animatedDialog.ignoreNextCallToHide = true
                     dialog.hide()
                 }
 
                 override fun onSizeChanged() {
-                    launchAnimation.onOriginalDialogSizeChanged()
+                    animatedDialog.onOriginalDialogSizeChanged()
+                }
+
+                override fun prepareForStackDismiss() {
+                    animatedDialog.touchSurface = animatedDialog.prepareForStackDismiss()
                 }
             })
         }
 
-        launchAnimation.start()
+        animatedDialog.start()
         return hostDialog
     }
 
     /**
+     * Launch [dialog] from a [parentHostDialog] as returned by [showFromView]. This will allow
+     * for dismissing the whole stack.
+     *
+     * This will return a new host dialog, with the same caveat as [showFromView].
+     *
+     * @see DialogListener.prepareForStackDismiss
+     */
+    fun showFromDialog(
+        dialog: Dialog,
+        parentHostDialog: Dialog,
+        animateBackgroundBoundsChange: Boolean = false
+    ): Dialog {
+        val view = parentHostDialog.findViewById<ViewGroup>(DIALOG_CONTENT_PARENT_ID)
+                ?.getChildAt(0)
+                ?: throw IllegalStateException("No dialog content parent found in host dialog")
+        return showFromView(dialog, view, animateBackgroundBoundsChange)
+    }
+
+    /**
      * Ensure that all dialogs currently shown won't animate into their touch surface when
      * dismissed.
      *
@@ -214,6 +244,12 @@
     /** Called when this dialog show() is called. */
     fun onShow()
 
+    /**
+     * Call before dismissing a stack of dialogs (dialogs launched from dialogs), so the topmost
+     * can animate directly into the original `touchSurface`.
+     */
+    fun prepareForStackDismiss()
+
     /** Called when this dialog size might have changed, e.g. because of configuration changes. */
     fun onSizeChanged()
 }
@@ -224,7 +260,7 @@
     hostDialogProvider: HostDialogProvider,
 
     /** The view that triggered the dialog after being tapped. */
-    private val touchSurface: View,
+    var touchSurface: View,
 
     /**
      * A callback that will be called with this [AnimatedDialog] after the dialog was
@@ -236,7 +272,10 @@
     private val originalDialog: Dialog,
 
     /** Whether we should animate the dialog background when its bounds change. */
-    private val animateBackgroundBoundsChange: Boolean
+    private val animateBackgroundBoundsChange: Boolean,
+
+    /** Launch animation corresponding to the parent [hostDialog]. */
+    private val parentAnimatedDialog: AnimatedDialog? = null
 ) {
     /**
      * The fullscreen dialog to which we will add the content view [originalDialogView] of
@@ -249,11 +288,12 @@
     private val hostDialogRoot = FrameLayout(context)
 
     /**
-     * The parent of the original dialog content view, that serves as a fake window that will have
-     * the same size as the original dialog window and to which we will set the original dialog
-     * window background.
+     * The dialog content with its background. When animating a fullscreen dialog, this is just the
+     * first ViewGroup of the dialog that has a background. When animating a normal (not fullscreen)
+     * dialog, this is an additional view that serves as a fake window that will have the same size
+     * as the original dialog window and to which we will set the original dialog window background.
      */
-    val dialogContentParent = FrameLayout(context)
+    var dialogContentWithBackground: ViewGroup? = null
 
     /**
      * The background color of [originalDialogView], taking into consideration the [originalDialog]
@@ -359,9 +399,7 @@
         // Make the touch surface invisible and make sure that it stays invisible as long as the
         // dialog is shown or animating.
         touchSurface.visibility = View.INVISIBLE
-        if (touchSurface is LaunchableView) {
-            touchSurface.setShouldBlockVisibilityChanges(true)
-        }
+        (touchSurface as? LaunchableView)?.setShouldBlockVisibilityChanges(true)
 
         // Add a pre draw listener to (maybe) start the animation once the touch surface is
         // actually invisible.
@@ -412,59 +450,87 @@
         hostDialogRoot.setOnClickListener { hostDialog.dismiss() }
         dialogView.isClickable = true
 
-        // Set the background of the window dialog to the dialog itself.
-        // TODO(b/193634619): Support dialog windows without background.
-        // TODO(b/193634619): Support dialog whose background comes from the content view instead of
-        // the window.
-        val typedArray =
-            originalDialog.context.obtainStyledAttributes(com.android.internal.R.styleable.Window)
-        val backgroundRes =
-            typedArray.getResourceId(com.android.internal.R.styleable.Window_windowBackground, 0)
-        typedArray.recycle()
-        if (backgroundRes == 0) {
-            throw IllegalStateException("Dialogs with no backgrounds on window are not supported")
+        // Remove the original dialog view from its parent.
+        (dialogView.parent as? ViewGroup)?.removeView(dialogView)
+
+        val originalDialogWindow = originalDialog.window!!
+        val isOriginalWindowFullScreen =
+            originalDialogWindow.attributes.width == ViewGroup.LayoutParams.MATCH_PARENT &&
+            originalDialogWindow.attributes.height == ViewGroup.LayoutParams.MATCH_PARENT
+        if (isOriginalWindowFullScreen) {
+            // If the original dialog window is fullscreen, then we look for the first ViewGroup
+            // that has a background and animate towards that ViewGroup given that this is probably
+            // what represents the actual dialog view.
+            dialogContentWithBackground = findFirstViewGroupWithBackground(dialogView)
+                ?: throw IllegalStateException("Unable to find ViewGroup with background")
+
+            hostDialogRoot.addView(
+                dialogView,
+
+                FrameLayout.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT,
+                    ViewGroup.LayoutParams.MATCH_PARENT
+                )
+            )
+        } else {
+            // Add a parent view to the original dialog view to which we will set the original
+            // dialog window background. This View serves as a fake window with background, so that
+            // we are sure that we don't override the original dialog content view paddings with the
+            // window background that usually has insets.
+            dialogContentWithBackground = FrameLayout(context).apply {
+                id = DIALOG_CONTENT_PARENT_ID
+
+                // TODO(b/193634619): Support dialog windows without background.
+                background = originalDialogWindow.decorView?.background
+                    ?: throw IllegalStateException(
+                        "Dialogs with no backgrounds on window are not supported")
+
+                addView(
+                    dialogView,
+
+                    // It should match its parent size, which is sized the same as the original
+                    // dialog window.
+                    FrameLayout.LayoutParams(
+                        ViewGroup.LayoutParams.MATCH_PARENT,
+                        ViewGroup.LayoutParams.MATCH_PARENT
+                    )
+                )
+            }
+
+            // Add the parent (that has the background) to the host window.
+            hostDialogRoot.addView(
+                dialogContentWithBackground,
+
+                // We give it the size and gravity of its original dialog window.
+                FrameLayout.LayoutParams(
+                    originalDialogWindow.attributes.width,
+                    originalDialogWindow.attributes.height,
+                    originalDialogWindow.attributes.gravity
+                )
+            )
         }
 
-        // Add a parent view to the original dialog view to which we will set the original dialog
-        // window background. This View serves as a fake window with background, so that we are sure
-        // that we don't override the dialog view paddings with the window background that usually
-        // has insets.
-        dialogContentParent.setBackgroundResource(backgroundRes)
-        hostDialogRoot.addView(
-            dialogContentParent,
+        val dialogContentWithBackground = this.dialogContentWithBackground!!
 
-            // We give it the size of its original dialog window.
-            FrameLayout.LayoutParams(
-                originalDialog.window.attributes.width,
-                originalDialog.window.attributes.height,
-                Gravity.CENTER
-            )
-        )
+        // Make the dialog and its background invisible for now, to make sure it's not drawn yet.
+        dialogContentWithBackground.visibility = View.INVISIBLE
 
-        // Make the dialog view parent invisible for now, to make sure it's not drawn yet.
-        dialogContentParent.visibility = View.INVISIBLE
-
-        val background = dialogContentParent.background!!
+        val background = dialogContentWithBackground.background!!
         originalDialogBackgroundColor =
             GhostedViewLaunchAnimatorController.findGradientDrawable(background)
                 ?.color
                 ?.defaultColor ?: Color.BLACK
 
-        // Add the dialog view to its parent (that has the original window background).
-        (dialogView.parent as? ViewGroup)?.removeView(dialogView)
-        dialogContentParent.addView(
-            dialogView,
-
-            // It should match its parent size, which is sized the same as the original dialog
-            // window.
-            FrameLayout.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                ViewGroup.LayoutParams.MATCH_PARENT
-            )
-        )
+        if (isOriginalWindowFullScreen) {
+            // If the original window is full screen, the ViewGroup with background might already be
+            // correctly laid out. Make sure we relayout and that the layout listener below is still
+            // called.
+            dialogContentWithBackground.layout(0, 0, 0, 0)
+            dialogContentWithBackground.requestLayout()
+        }
 
         // Start the animation when the dialog is laid out in the center of the host dialog.
-        dialogContentParent.addOnLayoutChangeListener(object : View.OnLayoutChangeListener {
+        dialogContentWithBackground.addOnLayoutChangeListener(object : View.OnLayoutChangeListener {
             override fun onLayoutChange(
                 view: View,
                 left: Int,
@@ -476,7 +542,7 @@
                 oldRight: Int,
                 oldBottom: Int
             ) {
-                dialogContentParent.removeOnLayoutChangeListener(this)
+                dialogContentWithBackground.removeOnLayoutChangeListener(this)
 
                 isOriginalDialogViewLaidOut = true
                 maybeStartLaunchAnimation()
@@ -484,6 +550,25 @@
         })
     }
 
+    private fun findFirstViewGroupWithBackground(view: View): ViewGroup? {
+        if (view !is ViewGroup) {
+            return null
+        }
+
+        if (view.background != null) {
+            return view
+        }
+
+        for (i in 0 until view.childCount) {
+            val match = findFirstViewGroupWithBackground(view.getChildAt(i))
+            if (match != null) {
+                return match
+            }
+        }
+
+        return null
+    }
+
     fun onOriginalDialogSizeChanged() {
         // The dialog is the single child of the root.
         if (hostDialogRoot.childCount != 1) {
@@ -532,7 +617,8 @@
                 // at the end of the launch animation, because the lauch animation already correctly
                 // handles bounds changes.
                 if (backgroundLayoutListener != null) {
-                    dialogContentParent.addOnLayoutChangeListener(backgroundLayoutListener)
+                    dialogContentWithBackground!!
+                        .addOnLayoutChangeListener(backgroundLayoutListener)
                 }
             }
         )
@@ -576,9 +662,7 @@
             Log.i(TAG, "Skipping animation of dialog into the touch surface")
 
             // Make sure we allow the touch surface to change its visibility again.
-            if (touchSurface is LaunchableView) {
-                touchSurface.setShouldBlockVisibilityChanges(false)
-            }
+            (touchSurface as? LaunchableView)?.setShouldBlockVisibilityChanges(false)
 
             // If the view is invisible it's probably because of us, so we make it visible again.
             if (touchSurface.visibility == View.INVISIBLE) {
@@ -598,15 +682,15 @@
             },
             onLaunchAnimationEnd = {
                 // Make sure we allow the touch surface to change its visibility again.
-                if (touchSurface is LaunchableView) {
-                    touchSurface.setShouldBlockVisibilityChanges(false)
-                }
+                (touchSurface as? LaunchableView)?.setShouldBlockVisibilityChanges(false)
 
                 touchSurface.visibility = View.VISIBLE
-                dialogContentParent.visibility = View.INVISIBLE
+                val dialogContentWithBackground = this.dialogContentWithBackground!!
+                dialogContentWithBackground.visibility = View.INVISIBLE
 
                 if (backgroundLayoutListener != null) {
-                    dialogContentParent.removeOnLayoutChangeListener(backgroundLayoutListener)
+                    dialogContentWithBackground
+                        .removeOnLayoutChangeListener(backgroundLayoutListener)
                 }
 
                 // The animated ghost was just removed. We create a temporary ghost that will be
@@ -639,8 +723,8 @@
     ) {
         // Create 2 ghost controllers to animate both the dialog and the touch surface in the host
         // dialog.
-        val startView = if (isLaunching) touchSurface else dialogContentParent
-        val endView = if (isLaunching) dialogContentParent else touchSurface
+        val startView = if (isLaunching) touchSurface else dialogContentWithBackground!!
+        val endView = if (isLaunching) dialogContentWithBackground!! else touchSurface
         val startViewController = GhostedViewLaunchAnimatorController(startView)
         val endViewController = GhostedViewLaunchAnimatorController(endView)
         startViewController.launchContainer = hostDialogRoot
@@ -701,7 +785,9 @@
     }
 
     private fun shouldAnimateDialogIntoView(): Boolean {
-        if (exitAnimationDisabled) {
+        // Don't animate if the dialog was previously hidden using hide() (either on the host dialog
+        // or on the original dialog) or if we disabled the exit animation.
+        if (exitAnimationDisabled || !hostDialog.isShowing) {
             return false
         }
 
@@ -796,4 +882,18 @@
             animator.start()
         }
     }
+
+    fun prepareForStackDismiss(): View {
+        if (parentAnimatedDialog == null) {
+            return touchSurface
+        }
+        parentAnimatedDialog.exitAnimationDisabled = true
+        parentAnimatedDialog.originalDialog.hide()
+        val view = parentAnimatedDialog.prepareForStackDismiss()
+        parentAnimatedDialog.originalDialog.dismiss()
+        // Make the touch surface invisible, so we end up animating to it when we actually
+        // dismiss the stack
+        view.visibility = View.INVISIBLE
+        return view
+    }
 }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
index 3ccf5e4..5fec4cc 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/GhostedViewLaunchAnimatorController.kt
@@ -53,8 +53,12 @@
     private val ghostedView: View,
 
     /** The [InteractionJankMonitor.CujType] associated to this animation. */
-    private val cujType: Int? = null
+    private val cujType: Int? = null,
+    private var interactionJankMonitor: InteractionJankMonitor? = null
 ) : ActivityLaunchAnimator.Controller {
+
+    constructor(view: View, type: Int) : this(view, type, null)
+
     /** The container to which we will add the ghost view and expanding background. */
     override var launchContainer = ghostedView.rootView as ViewGroup
     private val launchContainerOverlay: ViewGroupOverlay
@@ -170,7 +174,7 @@
         val matrix = ghostView?.animationMatrix ?: Matrix.IDENTITY_MATRIX
         matrix.getValues(initialGhostViewMatrixValues)
 
-        cujType?.let { InteractionJankMonitor.getInstance().begin(ghostedView, it) }
+        cujType?.let { interactionJankMonitor?.begin(ghostedView, it) }
     }
 
     override fun onLaunchAnimationProgress(
@@ -251,7 +255,7 @@
             return
         }
 
-        cujType?.let { InteractionJankMonitor.getInstance().end(it) }
+        cujType?.let { interactionJankMonitor?.end(it) }
 
         backgroundDrawable?.wrapped?.alpha = startBackgroundAlpha
 
diff --git a/packages/SystemUI/docs/keyguard/bouncer.md b/packages/SystemUI/docs/keyguard/bouncer.md
index 51f8516..4bfe734 100644
--- a/packages/SystemUI/docs/keyguard/bouncer.md
+++ b/packages/SystemUI/docs/keyguard/bouncer.md
@@ -2,15 +2,24 @@
 
 [KeyguardBouncer][1] is the component responsible for displaying the security method set by the user (password, PIN, pattern) as well as SIM-related security methods, allowing the user to unlock the device or SIM.
 
+## Supported States
+
+1. Phone, portrait mode - The default and typically only way to view the bouncer. Screen cannot rotate.
+1. Phone, landscape - Can only get into this state via lockscreen activities. Launch camera, rotate to landscape, tap lock icon is one example.
+1. Foldables - Both landscape and portrait are supported. In landscape, the bouncer can appear on either of the hinge and can be dragged to the other side. Also refered to as "OneHandedMode in [KeyguardSecurityContainerController][3]
+1. Tablets - The bouncer is supplemented with user icons and a multi-user switcher, when available.
+
 ## Components
 
 The bouncer contains a hierarchy of controllers/views to render the user's security method and to manage the authentication attempts.
 
 1. [KeyguardBouncer][1] - Entrypoint for managing the bouncer visibility.
     1. [KeyguardHostViewController][2] - Intercepts media keys. Can most likely be merged with the next item.
-        1. [KeyguardSecurityContainerController][3] - Manages unlock attempt responses, one-handed use
+        1. [KeyguardSecurityContainerController][3] - Manages unlock attempt responses, determines the correct security view layout, which may include a user switcher or enable one-handed use.
             1. [KeyguardSecurityViewFlipperController][4] - Based upon the [KeyguardSecurityModel#SecurityMode][5], will instantiate the required view and controller. PIN, Pattern, etc.
 
+Fun fact: Naming comes from the concept of a bouncer at a bar or nightclub, who prevent troublemakers from entering or eject them from the premises.
+
 [1]: /frameworks/base/packages/SystemUI/com/android/systemui/statusbar/phone/KeyguardBouncer
 [2]: /frameworks/base/packages/SystemUI/com/android/keyguard/KeyguardHostViewController
 [3]: /frameworks/base/packages/SystemUI/com/android/keyguard/KeyguardSecurityContainerController
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
index b83ea4a..d5f858c 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
@@ -34,7 +34,7 @@
 
     String ACTION = "com.android.systemui.action.PLUGIN_QS";
 
-    int VERSION = 11;
+    int VERSION = 12;
 
     String TAG = "QS";
 
@@ -46,6 +46,8 @@
     void setHeightOverride(int desiredHeight);
     void setHeaderClickable(boolean qsExpansionEnabled);
     boolean isCustomizing();
+    /** Close the QS customizer, if it is open. */
+    void closeCustomizer();
     void setOverscrolling(boolean overscrolling);
     void setExpanded(boolean qsExpanded);
     void setListening(boolean listening);
diff --git a/packages/SystemUI/res-keyguard/values-af/strings.xml b/packages/SystemUI/res-keyguard/values-af/strings.xml
index 5346fb6..74a7123 100644
--- a/packages/SystemUI/res-keyguard/values-af/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-af/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Tik PIN-kode in"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Tik SIM se PUK- en nuwe PIN-kode in"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM se PUK-kode"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"SIM se nuwe PIN-kode"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Raak om wagwoord in te tik"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Voer wagwoord in om te ontsluit"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Tik PIN in om te ontsluit"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Voer jou PIN in"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Voer jou patroon in"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Voer jou wagwoord in"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Verkeerde PIN-kode."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ongeldige kaart."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Gelaai"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans draadloos"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans vinnig"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laai tans stadig"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laaiproses word tydelik beperk"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Koppel jou laaier."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk Kieslys om te ontsluit."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk is gesluit"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Geen SIM-kaart nie"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Toestelwagwoord"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM-PIN-area"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM-PUK-area"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Volgende wekker gestel vir <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Vee uit"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Deaktiveer e-SIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Kan nie e-SIM deaktiveer nie"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Die e-SIM kan weens \'n fout nie gedeaktiveer word nie."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Het jy die patroon vergeet?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Verkeerde patroon"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Verkeerde wagwoord"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Verkeerde PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Probeer oor <xliff:g id="NUMBER">%d</xliff:g> sekondes weer.</item>
       <item quantity="one">Probeer oor 1 sekonde weer.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Teken jou patroon"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Voer SIM se PIN in."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Voer SIM se PIN vir \"<xliff:g id="CARRIER">%1$s</xliff:g>\" in."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Deaktiveer e-SIM om toestel sonder mobiele diens te gebruik."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Voer PIN in"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Voer wagwoord in"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is nou gedeaktiveer. Voer PUK-kode in om voort te gaan. Kontak diensverskaffer vir besonderhede."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM vir \"<xliff:g id="CARRIER">%1$s</xliff:g>\" is nou gedeaktiveer. Voer die PUK-kode in om voort te gaan. Kontak die diensverskaffer vir besonderhede."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Voer die gewenste PIN-kode in"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Ontsluit tans SIM-kaart …"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Tik \'n PIN wat 4 to 8 syfers lank is, in."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-kode moet 8 of meer syfers wees."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Voer die korrekte PUK-kode weer in. Herhaalde pogings sal die SIM permanent deaktiveer."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Te veel patroonpogings"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Jy het jou PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd ingetik. \n\nProbeer weer oor <xliff:g id="NUMBER_1">%2$d</xliff:g> sekondes."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Jy het jou wagwoord <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd ingetik. \n\nProbeer weer oor <xliff:g id="NUMBER_1">%2$d</xliff:g> sekondes."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Jy het jou ontsluitpatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer verkeerd geteken. \n\nProbeer weer oor <xliff:g id="NUMBER_1">%2$d</xliff:g> sekondes."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM-PIN-bewerking het misluk!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM-PUK-bewerking het misluk!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kode is aanvaar!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Geen diens nie."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Wissel invoermetode"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Vliegtuigmodus"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Patroon word vereis nadat toestel herbegin het"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Patroon word vir bykomende sekuriteit vereis"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN word vir bykomende sekuriteit vereis"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Wagwoord word vir bykomende sekuriteit vereis"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Patroon word vereis wanneer jy profiele wissel"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PIN word vereis wanneer jy profiele wissel"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Wagwoord word vereis wanneer jy profiele wissel"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Toestel is deur administrateur gesluit"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Toestel is handmatig gesluit"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Toestel is <xliff:g id="NUMBER_1">%d</xliff:g> uur lank nie ontsluit nie. Bevestig patroon.</item>
-      <item quantity="one">Toestel is <xliff:g id="NUMBER_0">%d</xliff:g> uur lank nie ontsluit nie. Bevestig patroon.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Toestel is <xliff:g id="NUMBER_1">%d</xliff:g> uur lank nie ontsluit nie. Bevestig PIN.</item>
-      <item quantity="one">Toestel is <xliff:g id="NUMBER_0">%d</xliff:g> uur lank nie ontsluit nie. Bevestig PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Toestel is <xliff:g id="NUMBER_1">%d</xliff:g> uur lank nie ontsluit nie. Bevestig wagwoord.</item>
-      <item quantity="one">Toestel is <xliff:g id="NUMBER_0">%d</xliff:g> uur lank nie ontsluit nie. Bevestig wagwoord.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nie herken nie"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nie herken nie"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-am/strings.xml b/packages/SystemUI/res-keyguard/values-am/strings.xml
index 80486ba..ef97693 100644
--- a/packages/SystemUI/res-keyguard/values-am/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-am/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"የቁልፍ ጥበቃ"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"ፒን ኮድ ይተይቡ"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"የሲም PUK እና አዲሱን ፒን ኮድ ይተይቡ"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"የሲም PUK ኮድ"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"አዲስ የሲም ፒን  ኮድ"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"የይለፍ ቃል ለመተየብ ይንኩ"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"ለመክፈት የይለፍ ቃል ይተይቡ"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"ለመክፈት ፒን ይተይቡ"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"የእርስዎን ፒን ያስገቡ"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"ሥርዓተ-ጥለትዎን ያስገቡ"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"ይለፍ ቃልዎን ያስገቡ"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"ትክክል ያልሆነ ፒን  ኮድ።"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ልክ ያልሆነ ካርድ።"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"ባትሪ ሞልቷል"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በገመድ አልባ ኃይል በመሙላት ላይ"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በፍጥነት ኃይልን በመሙላት ላይ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • በዝግታ ኃይልን በመሙላት ላይ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ኃይል መሙላት ለጊዜው ተገድቧል"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"ኃይል መሙያዎን ያያይዙ።"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ለመክፈት ምናሌ ተጫን።"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"አውታረ መረብ ተቆልፏል"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ምንም ሲም ካርድ የለም"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"የመሣሪያ ይለፍ ቃል"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"የሲም ፒን አካባቢ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"የሲም PUK አካባቢ"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"ቀጣዩ ማንቂያ ለ<xliff:g id="ALARM">%1$s</xliff:g> ተዘጋጅቷል"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"ሰርዝ"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIMን አሰናክል"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIMን ማሰናከል አልተቻለም"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"በአንድ ስህተት ምክንያት eSIM ሊሰናከል አልቻለም።"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"አስገባ"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"ስርዓተ ጥለቱን እርሳ"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"የተሳሳተ ሥርዓተ ጥለት"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"የተሳሳተ የይለፍ ቃል"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"የተሳሳተ ፒን"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">በ<xliff:g id="NUMBER">%d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።</item>
       <item quantity="other">በ<xliff:g id="NUMBER">%d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"ስርዓተ ጥለትዎን ይሳሉ"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"የሲም ፒን ያስገቡ።"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"የ«<xliff:g id="CARRIER">%1$s</xliff:g>» ሲም ፒን ያስገቡ።"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> መሣሪያን ያለሞባይል አገልግሎት ለመጠቀም eSIMን ያሰናክሉ።"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"ፒን ያስገቡ"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"የይለፍ ቃል ያስገቡ"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"ሲም አሁን ተሰናክሏል። ለመቀጠል የPUK ኮድ ያስገቡ። ለዝርዝር አገልግሎት አቅራቢን ያግኙ።"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"ሲም «<xliff:g id="CARRIER">%1$s</xliff:g>» አሁን ተሰናክሏል። ለመቀጠል የPUK ኮድ ያስገቡ። ዝርዝር መረጃን ለማግኘት የተንቀሳቃሽ ስልክ አገልግሎት አቅራቢውን ያነጋግሩ።"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"የተፈለገውን የፒን ኮድ ያስገቡ"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"ሲም ካርድን በመክፈት ላይ..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"ከ4 እስከ 8 ቁጥሮች የያዘ ፒን ይተይቡ።"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"የPUK ኮድ 8 ወይም ከዚያ በላይ ቁጥሮች ሊኖረው ይገባል።"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"ትክክለኛውን የPUK ኮድ እንደገና ያስገቡ። ተደጋጋሚ ሙከራዎች ሲሙን እስከመጨረሻው ያሰናክሉታል።"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"በጣም ብዙ የስርዓተ ጥለት ሙከራዎች"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ፒንዎን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ በትክክል አልተየቡም። \n\nበ<xliff:g id="NUMBER_1">%2$d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"የይለፍ ቃልዎን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መንገድ ተይበዋል።\n\nበ<xliff:g id="NUMBER_1">%2$d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"የመክፈቻ ስርዓተ ጥለቱን <xliff:g id="NUMBER_0">%1$d</xliff:g> ጊዜ ትክክል ባልሆነ መንገድ ስለውታል።\n\nበ<xliff:g id="NUMBER_1">%2$d</xliff:g> ሰኮንዶች ውስጥ እንደገና ይሞክሩ።"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"የሲም ፒን ክወና አልተሳካም!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"የሲም PUK ክወና አልተሳካም!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"ኮዱ ተቀባይነት አግኝቷል!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"ከአገልግሎት መስጫ ክልል ውጪ።"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"የግቤት ስልት ቀይር"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"የአውሮፕላን ሁነታ"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"መሣሪያ ዳግም ከጀመረ በኋላ ሥርዓተ ጥለት ያስፈልጋል"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ሥርዓተ ጥለት ለተጨማሪ ደህንነት ያስፈልጋል"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ፒን ለተጨማሪ ደህንነት ያስፈልጋል"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"የይለፍ ቃል ለተጨማሪ ደህንነት ያስፈልጋል"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"መገለጫዎችን በሚቀያይሯቸው ጊዜ ሥርዓተ ጥለት ያስፈልጋል"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"መገለጫዎችን በሚቀያይሯቸው ጊዜ ፒን ያስፈልጋል"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"መገለጫዎችን በሚቀያይሯቸው ጊዜ የይለፍ ቃል ያስፈልጋል"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"መሣሪያ በአስተዳዳሪ ተቆልፏል"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"መሣሪያ በተጠቃሚው ራሱ ተቆልፏል"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">ው ለ<xliff:g id="NUMBER_1">%d</xliff:g> ሰዓቶች አልተከፈተም ነበር። ስርዓተ-ጥለት ያረጋግጡ።</item>
-      <item quantity="other">መሣሪያው ለ<xliff:g id="NUMBER_1">%d</xliff:g> ሰዓቶች አልተከፈተም ነበር። ስርዓተ-ጥለት ያረጋግጡ።</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">መሣሪያው ለ<xliff:g id="NUMBER_1">%d</xliff:g> ሰዓቶች አልተከፈተም ነበር። ፒን ያረጋግጡ።</item>
-      <item quantity="other">መሣሪያው ለ<xliff:g id="NUMBER_1">%d</xliff:g> ሰዓቶች አልተከፈተም ነበር። ፒን ያረጋግጡ።</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">መሣሪያው ለ<xliff:g id="NUMBER_1">%d</xliff:g> ሰዓቶች አልተከፈተም ነበር። የይለፍ ቃል ያረጋግጡ።</item>
-      <item quantity="other">መሣሪያው ለ<xliff:g id="NUMBER_1">%d</xliff:g> ሰዓቶች አልተከፈተም ነበር። የይለፍ ቃል ያረጋግጡ።</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"አልታወቀም"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"አልታወቀም"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index f1ae7d4..d44a861 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"تأمين المفاتيح"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"اكتب رمز رقم التعريف الشخصي"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"‏أدخل رمز PUK لشريحة SIM ورمز \"رقم التعريف الشخصي\" الجديد"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"‏رمز PUK لشريحة SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"‏رمز رقم تعريف شخصي جديد لشريحة SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"المس لكتابة كلمة المرور"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"اكتب كلمة المرور لإلغاء التأمين"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"اكتب رمز رقم التعريف الشخصي لإلغاء التأمين"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"‏أدخل رقم التعريف الشخصي (PIN)"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"أدخل النقش"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"أدخل كلمة المرور"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"رمز رقم التعريف الشخصي غير صحيح."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"بطاقة غير صالحة."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"تم الشحن"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن لاسلكيًا"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن سريعًا"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • جارٍ الشحن ببطء"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • الشحن محدود مؤقتًا"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"توصيل جهاز الشحن."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"اضغط على \"القائمة\" لإلغاء التأمين."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"الشبكة مؤمّنة"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"‏ليست هناك شريحة SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"كلمة مرور الجهاز"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"‏منطقة رقم التعريف الشخصي لشريحة SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"‏منطقة PUK لشريحة SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"تم ضبط التنبيه التالي على <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Delete"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"‏إيقاف شريحة eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"‏يتعذّر إيقاف eSIM."</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"‏يتعذّر إيقاف eSIM بسبب خطأ."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"نسيت النقش"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"النقش غير صحيح"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"كلمة مرور غير صحيحة"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"رقم تعريف شخصي خاطئ"</string>
@@ -72,12 +60,9 @@
       <item quantity="other">حاول مرة أخرى خلال <xliff:g id="NUMBER">%d</xliff:g> ثانية.</item>
       <item quantity="one">حاول مرة أخرى خلال ثانية واحدة.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"ارسم نقشك"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"‏أدخل رقم التعريف الشخصي لشريحة SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"‏أدخل رقم التعريف الشخصي لشريحة SIM التابعة للمشغّل \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"‏<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> يجب إيقاف eSIM لاستخدام الجهاز بدون خدمة الأجهزة الجوّالة."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"أدخل رقم التعريف الشخصي"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"أدخل كلمة المرور"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"‏شريحة SIM غير مفعّلة الآن. أدخل رمز PUK للمتابعة. اتصل بمشغل شبكة الجوّال للاطلاع على التفاصيل."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"‏SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" غير مفعّلة الآن. أدخل رمز PUK للمتابعة. واتصل بمشغل شبكة الجوّال لمعرفة التفاصيل."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"أدخل رمز رقم التعريف الشخصي المطلوب"</string>
@@ -85,8 +70,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"‏جارٍ فتح قفل شريحة SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"اكتب رمز رقم التعريف الشخصي المكوّن من ٤ إلى ٨ أرقام."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"‏يجب أن يتضمن رمز PUK‏ ۸ أرقام أو أكثر."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"‏أعد إدخال رمز PUK الصحيح. وستؤدي المحاولات المتكررة إلى إيقاف شريحة SIM نهائيًا."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"محاولات النقش كثيرة جدًا"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"لقد كتبت رقم التعريف الشخصي بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"لقد كتبت كلمة المرور بشكل غير صحيح <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"لقد رسمت نقش فتح القفل بطريقة غير صحيحة <xliff:g id="NUMBER_0">%1$d</xliff:g> مرة. \n\nأعد المحاولة خلال <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانية."</string>
@@ -110,8 +93,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"‏تعذّر إتمام عملية \"رقم التعريف الشخصي\" لشريحة SIM"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"‏تعذّر إتمام عملية PUK لشريحة SIM"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"تم قبول الرمز"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"لا تتوفر خدمة."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"تبديل أسلوب الإدخال"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"وضع الطيران"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"يجب رسم النقش بعد إعادة تشغيل الجهاز"</string>
@@ -120,35 +101,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"يجب رسم النقش لمزيد من الأمان"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"يجب إدخال رقم التعريف الشخصي لمزيد من الأمان"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"يجب إدخال كلمة المرور لمزيد من الأمان"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"يجب رسم النقش عند تبديل الملفات الشخصية"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"يجب إدخال رقم التعريف الشخصي عند تبديل الملفات الشخصية"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"يجب إدخال كلمة المرور عند تبديل الملفات الشخصية."</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"اختار المشرف قفل الجهاز"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"تم حظر الجهاز يدويًا"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="zero">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعة. تأكيد النقش.</item>
-      <item quantity="two">لم يتم فتح قفل الجهاز لمدة ساعتين (<xliff:g id="NUMBER_1">%d</xliff:g>). تأكيد النقش.</item>
-      <item quantity="few">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعات. تأكيد النقش.</item>
-      <item quantity="many">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعة. تأكيد النقش.</item>
-      <item quantity="other">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعة. تأكيد النقش.</item>
-      <item quantity="one">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_0">%d</xliff:g> ساعة. تأكيد النقش.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="zero">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعة. تأكيد رقم التعريف الشخصي.</item>
-      <item quantity="two">لم يتم فتح قفل الجهاز لمدة ساعتين (<xliff:g id="NUMBER_1">%d</xliff:g>). تأكيد رقم التعريف الشخصي.</item>
-      <item quantity="few">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعة. تأكيد رقم التعريف الشخصي.</item>
-      <item quantity="many">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعة. تأكيد رقم التعريف الشخصي.</item>
-      <item quantity="other">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعة. تأكيد رقم التعريف الشخصي.</item>
-      <item quantity="one">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_0">%d</xliff:g> ساعة. تأكيد رقم التعريف الشخصي.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="zero">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعة. تأكيد كلمة المرور.</item>
-      <item quantity="two">لم يتم فتح قفل الجهاز لمدة ساعتين (<xliff:g id="NUMBER_1">%d</xliff:g>). تأكيد كلمة المرور.</item>
-      <item quantity="few">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعات. تأكيد كلمة المرور.</item>
-      <item quantity="many">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعة. تأكيد كلمة المرور.</item>
-      <item quantity="other">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_1">%d</xliff:g> ساعة. تأكيد كلمة المرور.</item>
-      <item quantity="one">لم يتم فتح قفل الجهاز لمدة <xliff:g id="NUMBER_0">%d</xliff:g> ساعة. تأكيد كلمة المرور.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"لم يتم التعرف عليها."</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"لم يتم التعرّف عليه."</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-as/strings.xml b/packages/SystemUI/res-keyguard/values-as/strings.xml
index 7bd4165..ab50326 100644
--- a/packages/SystemUI/res-keyguard/values-as/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-as/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"কীগাৰ্ড"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"পিন ক\'ড লিখক"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"ছিমৰ PUK আৰু নতুন পিন ক\'ড লিখক"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"ছিমৰ PUK ক\'ড"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"নতুন ছিমৰ পিন ক\'ড"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"পাছৱৰ্ড লিখিবলৈ স্পৰ্শ কৰক"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"আনলক কৰিবলৈ পাছৱৰ্ড লিখক"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"আনলক কৰিবলৈ পিন লিখক"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"আপোনাৰ পিন দিয়ক"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"আপোনাৰ আৰ্হি দিয়ক"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"আপোনাৰ পাছৱর্ড দিয়ক"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"ভুল পিন ক\'ড।"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ব্যৱহাৰৰ অযোগ্য ছিম কাৰ্ড"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"চ্চার্জ কৰা হ’ল"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • বেতাঁৰৰ জৰিয়তে চাৰ্জ কৰি থকা হৈছে"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্ৰুত গতিৰে চ্চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • লাহে লাহে চ্চাৰ্জ কৰি থকা হৈছে"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চাৰ্জ কৰাটো সাময়িকভাৱে সীমিত কৰা হৈছে"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"আপোনাৰ চ্চার্জাৰ সংযোগ কৰক।"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক কৰিবলৈ মেনু টিপক।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটৱর্ক লক কৰা অৱস্থাত আছে"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"কোনো ছিম কাৰ্ড নাই"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"ডিভাইচৰ পাছৱৰ্ড"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"ছিম পিনৰ ক্ষেত্ৰ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"ছিমৰ PUK ক্ষেত্ৰ"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"পৰৱৰ্তী এলাৰ্ম <xliff:g id="ALARM">%1$s</xliff:g> বজাত ছেট কৰা হৈছে"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"মচক"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"ই-ছিম অক্ষম কৰক"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"ই-ছিম অক্ষম কৰিব পৰা নাযায়"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"এটা আসোঁৱাহৰ কাৰণে ই-ছিম অক্ষম কৰিব পৰা নাযায়।"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"এণ্টাৰ বুটাম"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"আৰ্হি পাহৰিলে নেকি"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"ভুল আৰ্হি"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"ভুল পাছৱৰ্ড"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"ভুল পিন"</string>
@@ -68,12 +56,9 @@
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> ছেকেণ্ডত আকৌ চেষ্টা কৰক।</item>
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> ছেকেণ্ডত আকৌ চেষ্টা কৰক।</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"আপোনাৰ আৰ্হি আঁকক"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"ছিমৰ পিন দিয়ক।"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\"ৰ ছিমৰ পিন দিয়ক।"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> ম’বাইল সেৱা অবিহনে ডিভাইচ ব্যৱহাৰ কৰিবলৈ ই-ছিম অক্ষম কৰক।"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"পিন দিয়ক"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"পাছৱৰ্ড দিয়ক"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"ছিমখন বর্তমান অক্ষম অৱস্থাত আছে। অব্যাহত ৰাখিবলৈ PUK ক\'ড লিখক। সবিশেষ জানিবলৈ বাহকৰ সৈতে যোগাযোগ কৰক।"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" ছিমখন বর্তমান অক্ষম অৱস্থাত আছে। অব্যাহত ৰাখিবলৈ PUK ক\'ড দিয়ক। সবিশেষ জানিবলৈ বাহকৰ সৈতে যোগাযোগ কৰক।"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"আপোনাৰ পছন্দৰ পিন ক\'ড লিখক"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"ছিম কার্ড আনলক কৰি থকা হৈছে…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"৪টাৰ পৰা ৮টা সংখ্যাযুক্ত এটা পিন লিখক।"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK ক\'ডটো ৮টা বা তাতকৈ অধিক সংখ্যা থকা হ\'ব লাগিব।"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"শুদ্ধ PUK ক\'ডটো পুনৰ দিয়ক। বাৰে বাৰে ভুল ক\'ড দিলে ছিমখন স্থায়ীভাৱে অক্ষম হ\'ব।"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"বহুতবাৰ ভুলকৈ আর্হি অঁকা হৈছে"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"আপুনি আপোনাৰ পিন <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ লিখিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"আপুনি আপোনাৰ পাছৱৰ্ড <xliff:g id="NUMBER_0">%1$d</xliff:g>বাৰ ভুলকৈ লিখিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ছেকেণ্ডৰ পাছত আকৌ চেষ্টা কৰক।"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"আপুনি আপোনাৰ আনলক আৰ্হি <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>ছেকেণ্ডৰ পিছত আকৌ চেষ্টা কৰক।"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"ছিম পিনৰ জৰিয়তে আনলক কৰিব পৰা নগ\'ল!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"ছিম PUKৰ জৰিয়তে আনলক কৰিব পৰা নগ\'ল!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"ক\'ড গ্ৰহণ কৰা হ’ল!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"কোনো সেৱা নাই।"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ইনপুট পদ্ধতি সলনি কৰক"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"এয়াৰপ্লেন ম\'ড"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পিছত আৰ্হি দিয়াটো বাধ্যতামূলক"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"অতিৰিক্ত সুৰক্ষাৰ বাবে আর্হি দিয়াটো বাধ্যতামূলক"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"অতিৰিক্ত সুৰক্ষাৰ বাবে পিন দিয়াটো বাধ্যতামূলক"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"অতিৰিক্ত সুৰক্ষাৰ বাবে পাছৱর্ড দিয়াটো বাধ্যতামূলক"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"প্ৰ\'ফাইল সলনি কৰোঁতে আৰ্হি দিয়াটো বাধ্যতামূলক"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"ডিভাইচ ৰিষ্টাৰ্ট হোৱাৰ পিছত পিন দিয়াটো বাধ্যতামূলক"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"প্ৰ\'ফাইল সলনি কৰোঁতে পাছৱৰ্ড দিয়াটো বাধ্যতামূলক"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"প্ৰশাসকে ডিভাইচ লক কৰি ৰাখিছে"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ডিভাইচটো মেনুৱেলভাৱে লক কৰা হৈছিল"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">ডিভাইচটো <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধৰি আনলক কৰা হোৱা নাই। আর্হি নিশ্চিত কৰক।</item>
-      <item quantity="other">ডিভাইচটো <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধৰি আনলক কৰা হোৱা নাই। আর্হি নিশ্চিত কৰক।</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">ডিভাইচটো <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধৰি আনলক কৰা হোৱা নাই। পিন নিশ্চিত কৰক।</item>
-      <item quantity="other">ডিভাইচটো <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধৰি আনলক কৰা হোৱা নাই। পিন নিশ্চিত কৰক।</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">ডিভাইচটো <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধৰি আনলক কৰা হোৱা নাই। পাছৱৰ্ড নিশ্চিত কৰক।</item>
-      <item quantity="other">ডিভাইচটো <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধৰি আনলক কৰা হোৱা নাই। পাছৱৰ্ড নিশ্চিত কৰক।</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"চিনাক্ত কৰিব পৰা নাই"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"চিনাক্ত কৰিব পৰা নাই"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-az/strings.xml b/packages/SystemUI/res-keyguard/values-az/strings.xml
index 8f8d1c5..6153591 100644
--- a/packages/SystemUI/res-keyguard/values-az/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-az/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Ekran kilidi"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"PIN kod daxil edin"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM PUK və yeni PIN kodu yazın"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK kod"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Yeni SIM PIN kod"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Parol daxil etmək üçün toxunun"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Kilidi açmaq üçün parol daxil edin"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Kilidi açmaq üçün PIN daxil edin"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"PIN kodu daxil edin"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Modeli daxil edin"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Şifrənizi daxil edin"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Yanlış PIN kod."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Yanlış Kart."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Enerji yığılıb"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Simsiz şəkildə batareya yığır"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sürətlə enerji yığır"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş enerji yığır"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj müvəqqəti məhdudlaşdırılıb"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Adapteri qoşun."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmaq üçün Menyu düyməsinə basın."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Şəbəkə kilidlidir"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM kart yoxdur."</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Cihaz parolu"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN sahəsi"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK sahəsi"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Növbəti zəng vaxtı: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Silin"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSİM\'i deaktiv edin"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM-i deaktiv etmək alınmadı"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM xəta səbəbi ilə deaktiv edilmədi."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Daxil edin"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Modeli unutmuşam"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Yanlış model"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Yanlış parol"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Yanlış PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> saniyə ərzində yenidən cəhd edin.</item>
       <item quantity="one">1 saniyə ərzində yenidən cəhd edin.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Modeli çəkin"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM PIN\'ni daxil edin."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" üçün SIM PIN\'ni daxil edin."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Mobil xidmət olmadan cihazı istifadə etmək üçün eSIM-i deaktiv edin."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"PIN daxil edin"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Parol daxil edin"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM indi deaktivdir. Davam etmək üçün PUK kod daxil edin. Ətraflı məlumat üçün operatorla əlaqə saxlayın."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" indi deaktivdir. Davam etmək üçün PUK kodu daxil edin. Ətraflı məlumat üçün operatorla əlaqə saxlayın."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"İstədiyiniz PIN kodu daxil edin"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM kartın kilidi açılır..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4-8 rəqəmli PIN daxil edin."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kod 8 rəqəm və ya daha çox olmalıdır."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Yenidən düzgün PUK kod daxil edin. Təkrarlanan cəhdlər SIM-i birdəfəlik sıradan çıxaracaq."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Həddindən çox model cəhdi"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN kodu <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış daxil etdiniz. \n \n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Parolu <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış daxil etdiniz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Kilid modelini <xliff:g id="NUMBER_0">%1$d</xliff:g> dəfə yanlış çəkdiniz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniyə sonra yenidən cəhd edin."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN əməliyyatı alınmadı!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK əməliyyatı alınmadı!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kod Qəbul Edildi!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Xidmət yoxdur."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Daxiletmə metoduna keçin"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Təyyarə rejimi"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Cihaz yenidən başladıqdan sonra model tələb olunur"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Əlavə təhlükəsizlik üçün model tələb olunur"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Əlavə təhlükəsizlik üçün PIN tələb olunur"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Əlavə təhlükəsizlik üçün parol tələb olunur"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Profillər arasında keçid edərkən model tələb olunur"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Profillər arasında keçid edərkən PIN kod tələb olunur"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Profillər arasında keçid edərkən parol tələb olunur"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Cihaz admin tərəfindən kilidlənib"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Cihaz əl ilə kilidləndi"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Cihaz <xliff:g id="NUMBER_1">%d</xliff:g> saat kiliddən çıxarılmayıb. Nümunə kodu təsdiq edin.</item>
-      <item quantity="one">Cihaz <xliff:g id="NUMBER_0">%d</xliff:g> saat kiliddən çıxarılmayıb. Nümunə kodu təsdiq edin.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Cihaz <xliff:g id="NUMBER_1">%d</xliff:g> saat kiliddən çıxarılmayıb. PIN kodu təsdiq edin.</item>
-      <item quantity="one">Cihaz <xliff:g id="NUMBER_0">%d</xliff:g> saat kiliddən çıxarılmayıb. PIN kodu təsdiq edin.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Cihaz <xliff:g id="NUMBER_1">%d</xliff:g> saat kiliddən çıxarılmayıb. Parolu təsdiq edin.</item>
-      <item quantity="one">Cihaz <xliff:g id="NUMBER_0">%d</xliff:g> saat kiliddən çıxarılmayıb. Parolu təsdiq edin.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Tanınmır"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Tanınmır"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
index aa66e49..52bbd4b 100644
--- a/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-b+sr+Latn/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Zaključavanje tastature"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Unesite PIN kôd"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Unesite PUK za SIM i novi PIN kôd"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK kôd za SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Novi PIN kôd za SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Dodirnite za unos lozinke"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Unesite lozinku da biste otključali"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Unesite PIN za otključavanje"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Unesite PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Unesite šablon"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Unesite lozinku"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN kôd je netačan."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Nevažeća kartica."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Napunjena je"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bežično punjenje"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo se puni"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo se puni"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je privremeno ograničeno"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Meni da biste otključali."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nema SIM kartice"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Lozinka za uređaj"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Oblast za PIN za SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Oblast za PUK za SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Sledeći alarm je podešen za <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Izbriši"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Onemogući eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Onemogućavanje eSIM-a nije uspelo"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM ne može da se onemogući zbog greške."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Zaboravio/la sam šablon"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Pogrešan šablon"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Pogrešna lozinka"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Pogrešan PIN"</string>
@@ -69,12 +57,9 @@
       <item quantity="few">Probajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekunde.</item>
       <item quantity="other">Probajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekundi.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Nacrtajte šablon"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Unesite PIN za SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Unesite PIN za SIM „<xliff:g id="CARRIER">%1$s</xliff:g>“."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Onemogućite eSIM da biste uređaj koristili bez mobilne usluge."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Unesite PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Unesite lozinku"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM kartica je sada onemogućena. Unesite PUK kôd da biste nastavili. Detaljne informacije potražite od mobilnog operatera."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM „<xliff:g id="CARRIER">%1$s</xliff:g>“ je sada onemogućen. Unesite PUK kôd da biste nastavili. Detaljne informacije potražite od mobilnog operatera."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Unesite željeni PIN kôd"</string>
@@ -82,8 +67,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM kartica se otključava…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Unesite PIN koji ima 4–8 brojeva."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kôd treba da ima 8 ili više brojeva."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Ponovo unesite tačan PUK kôd. Ponovljeni pokušaji će trajno onemogućiti SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Previše pokušaja unosa šablona"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Uneli ste pogrešan PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Uneli ste pogrešnu lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Nacrtali ste netačan šablon za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nProbajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
@@ -101,8 +84,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Radnja sa PIN kodom za SIM nije uspela!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Radnja sa PUK kodom za SIM nije uspela!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kôd je prihvaćen!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Mreža nije dostupna."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Promeni metod unosa"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Režim rada u avionu"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Treba da unesete šablon kada se uređaj ponovo pokrene"</string>
@@ -111,26 +92,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Treba da unesete šablon radi dodatne bezbednosti"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Treba da unesete PIN radi dodatne bezbednosti"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Treba da unesete lozinku radi dodatne bezbednosti"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Treba da unesete šablon kada prelazite sa jednog profila na drugi"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Treba da unesete PIN kada prelazite sa jednog profila na drugi"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Treba da unesete lozinku kada prelazite sa jednog profila na drugi"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administrator je zaključao uređaj"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Uređaj je ručno zaključan"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Niste otključali uređaj <xliff:g id="NUMBER_1">%d</xliff:g> sat. Potvrdite šablon.</item>
-      <item quantity="few">Niste otključali uređaj <xliff:g id="NUMBER_1">%d</xliff:g> sata. Potvrdite šablon.</item>
-      <item quantity="other">Niste otključali uređaj <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite šablon.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Niste otključali uređaj <xliff:g id="NUMBER_1">%d</xliff:g> sat. Potvrdite PIN.</item>
-      <item quantity="few">Niste otključali uređaj <xliff:g id="NUMBER_1">%d</xliff:g> sata. Potvrdite PIN.</item>
-      <item quantity="other">Niste otključali uređaj <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Niste otključali uređaj <xliff:g id="NUMBER_1">%d</xliff:g> sat. Potvrdite lozinku.</item>
-      <item quantity="few">Niste otključali uređaj <xliff:g id="NUMBER_1">%d</xliff:g> sata. Potvrdite lozinku.</item>
-      <item quantity="other">Niste otključali uređaj <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite lozinku.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nije prepoznat"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nije prepoznat"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-be/strings.xml b/packages/SystemUI/res-keyguard/values-be/strings.xml
index 3ddf19d..d18fefa3 100644
--- a/packages/SystemUI/res-keyguard/values-be/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-be/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Увядзіце PIN-код"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Увядзіце PUK-код і новы PIN-код SIM-карты"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK-код SIM-карты"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Новы PIN-код SIM-карты"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Дакраніцеся, каб увесці пароль"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Увядзіце пароль для разблакіравання"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Каб разблакіраваць, увядзіце PIN-код"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Увядзіце PIN-код"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Увядзіце ўзор разблакіроўкі"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Увядзіце пароль"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Няправільны PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Несапраўдная картка."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Зараджаны"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе бесправадная зарадка"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе хуткая зарадка"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ідзе павольная зарадка"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарадка часова абмежавана"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Падключыце зарадную прыладу."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Націсніце кнопку \"Меню\", каб разблакіраваць."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сетка заблакіравана"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Няма SIM-карты"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Пароль прылады"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Поле для PIN-кода SIM-карты"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Поле для PUK-кода SIM-карты"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Наступны будзільнік пастаўлены на <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Выдаліць"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Адключыць eSIM-карту"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Немагчыма адключыць eSIM-карту"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Немагчыма адключыць eSIM-карту з-за памылкі."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Увесці"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Забыў(-ла) узор"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Няправільны ўзор разблакіроўкі"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Няправільны пароль"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Няправільны PIN-код"</string>
@@ -70,12 +58,9 @@
       <item quantity="many">Паўтарыце спробу праз <xliff:g id="NUMBER">%d</xliff:g> секунд.</item>
       <item quantity="other">Паўтарыце спробу праз <xliff:g id="NUMBER">%d</xliff:g> секунды.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Намалюйце ўзор"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Увядзіце PIN-код SIM-карты."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Увядзіце PIN-код SIM-карты для \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Каб выкарыстоўваць прыладу без мабільнай сувязі, адключыце eSIM-карту."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Увядзіце PIN-код"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Увядзіце пароль"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM-карта зараз адключана. Увядзіце PUK-код, каб працягнуць. Звяжыцеся са сваім аператарам, каб атрымаць дадатковую інфармацыю."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM-карта \"<xliff:g id="CARRIER">%1$s</xliff:g>\" зараз адключана. Увядзіце PUK-код, каб працягнуць. Каб атрымаць дадатковую інфармацыю, звяжыцеся з аператарам."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Увядзіце пажаданы PIN-код"</string>
@@ -83,8 +68,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Ідзе разблакіроўка SIM-карты…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Увядзіце PIN-код, які змяшчае ад 4 да 8 лічбаў."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-код павінен утрымліваць 8 лічбаў ці больш."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Паўторна ўвядзіце правільны PUK-код. Паўторныя спробы прывядуць да адключэння SIM-карты назаўсёды."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Занадта шмат спроб уводу ўзору"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Вы няправільна ўвялі PIN-код столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПаўтарыце спробу праз <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Вы няправільна ўвялі пароль столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПаўтарыце спробу праз <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Вы няправільна ўвялі ўзор разблакіроўкі столькі разоў: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПаўтарыце спробу праз <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
@@ -104,8 +87,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Разблакіраваць SIM-карту PIN-кодам не атрымалася!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Разблакіраваць SIM-карту PUK-кодам не атрымалася!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Код прыняты!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Не абслугоўваецца."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Пераключэнне рэжыму ўводу"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Рэжым палёту"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Пасля перазапуску прылады патрабуецца ўзор"</string>
@@ -114,29 +95,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Для забеспячэння дадатковай бяспекі патрабуецца ўзор"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Для забеспячэння дадатковай бяспекі патрабуецца PIN-код"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Для забеспячэння дадатковай бяспекі патрабуецца пароль"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Пры пераключэнні профіляў патрабуецца ўзор"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Пры пераключэнні профіляў патрабуецца PIN-код"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Пры пераключэнні профіляў патрабуецца пароль"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Прылада заблакіравана адміністратарам"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Прылада была заблакіравана ўручную"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзіны. Увядзіце ўзор.</item>
-      <item quantity="few">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзін. Увядзіце ўзор.</item>
-      <item quantity="many">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзін. Увядзіце ўзор.</item>
-      <item quantity="other">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзіны. Увядзіце ўзор.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзіны. Увядзіце PIN-код.</item>
-      <item quantity="few">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзін. Увядзіце PIN-код.</item>
-      <item quantity="many">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзін. Увядзіце PIN-код.</item>
-      <item quantity="other">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзіны. Увядзіце PIN-код.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзіны. Увядзіце пароль.</item>
-      <item quantity="few">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзін. Увядзіце пароль.</item>
-      <item quantity="many">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзін. Увядзіце пароль.</item>
-      <item quantity="other">Прылада не была разблакіравана на працягу <xliff:g id="NUMBER_1">%d</xliff:g> гадзіны. Увядзіце пароль.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Не распазнана"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Не распазнана"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-bg/strings.xml b/packages/SystemUI/res-keyguard/values-bg/strings.xml
index 6bb98df..256672b 100644
--- a/packages/SystemUI/res-keyguard/values-bg/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bg/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Въведете ПИН кода"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Въведете PUK за SIM картата и новия ПИН код"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK код за SIM картата"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Нов ПИН код за SIM картата"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Докоснете и въведете парола"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Въведете парола, за да отключите"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Въведете ПИН кода, за да отключите"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Въведете ПИН кода си"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Въведете фигурата си"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Въведете паролата си"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Неправилен ПИН код."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Картата е невалидна."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Заредена"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се безжично"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бързо"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарежда се бавно"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зареждането временно е ограничено"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Свържете зарядното си устройство."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натиснете „Меню“, за да отключите."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заключена"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Няма SIM карта"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Парола за устройството"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Област за ПИН кода на SIM картата"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Област за PUK кода на SIM картата"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Следващият будилник е зададен за <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Изтриване"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Деактивиране на ел. SIM карта"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Електронната SIM карта не може да бъде деактивирана"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Електронната SIM карта не може да бъде деактивирана поради грешка."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"„Enter“"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Забравена фигура"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Грешна фигура"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Грешна парола"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Грешен ПИН код"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Опитайте отново след <xliff:g id="NUMBER">%d</xliff:g> секунди.</item>
       <item quantity="one">Опитайте отново след 1 секунда.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Начертайте фигурата си"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Въведете ПИН кода за SIM картата."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Въведете ПИН кода на SIM картата за „<xliff:g id="CARRIER">%1$s</xliff:g>“."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Деактивирайте електронната SIM карта, за да използвате устройството без мобилна услуга."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Въведете ПИН кода"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Въведете паролата"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM картата вече е деактивирана. Въведете PUK кода, за да продължите. Свържете се с оператора за подробности."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM картата „<xliff:g id="CARRIER">%1$s</xliff:g>“ вече е деактивирана. Въведете PUK кодa, за да продължите. Свържете се с оператора за подробности."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Въведете желания ПИН код"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM картата се отключва..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Въведете ПИН код с четири до осем цифри."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK кодът трябва да е с осем или повече цифри."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Въведете отново правилния PUK код. Многократните опити ще деактивират за постоянно SIM картата."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Опитите за фигурата са твърде много"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Въведохте неправилно ПИН кода си <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. \n\nОпитайте отново след <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Въведохте неправилно паролата си <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. \n\nОпитайте отново след <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Начертахте неправилно фигурата си за отключване <xliff:g id="NUMBER_0">%1$d</xliff:g> пъти. \n\nОпитайте отново след <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Операцията с ПИН кода за SIM картата не бе успешна!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Операцията с PUK кода за SIM картата не бе успешна!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Кодът е приет!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Няма покритие."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Превключване на метода на въвеждане"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Самолетен режим"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"След рестартиране на устройството се изисква фигура"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"За допълнителна сигурност се изисква фигура"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"За допълнителна сигурност се изисква ПИН код"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"За допълнителна сигурност се изисква парола"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"При превключване между потребителските профили се изисква фигура"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"При превключване между потребителските профили се изисква ПИН код"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"При превключване между потребителските профили се изисква парола"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Устройството е заключено от администратора"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Устройството бе заключено ръчно"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Устройството не е отключвано от <xliff:g id="NUMBER_1">%d</xliff:g> часа. Потвърдете фигурата.</item>
-      <item quantity="one">Устройството не е отключвано от <xliff:g id="NUMBER_0">%d</xliff:g> час. Потвърдете фигурата.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Устройството не е отключвано от <xliff:g id="NUMBER_1">%d</xliff:g> часа. Потвърдете ПИН кода.</item>
-      <item quantity="one">Устройството не е отключвано от <xliff:g id="NUMBER_0">%d</xliff:g> час. Потвърдете ПИН кода.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Устройството не е отключвано от <xliff:g id="NUMBER_1">%d</xliff:g> часа. Потвърдете паролата.</item>
-      <item quantity="one">Устройството не е отключвано от <xliff:g id="NUMBER_0">%d</xliff:g> час. Потвърдете паролата.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Не е разпознато"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Не е разпознато"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-bn/strings.xml b/packages/SystemUI/res-keyguard/values-bn/strings.xml
index 2908bae..74fed29 100644
--- a/packages/SystemUI/res-keyguard/values-bn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bn/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"কীগার্ড"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"পিন কোড লিখুন"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"সিম PUK এবং নতুন পিন কোড লিখুন"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"সিম PUK কোড"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"নতুন সিম পিন কোড"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"পাসওয়ার্ড লিখতে স্পর্শ করুন"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"আনলক করতে পাসওয়ার্ড লিখুন"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"আনলক করতে পিন লিখুন"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"পিন লিখুন"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"প্যাটার্ন আঁকুন"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"পাসওয়ার্ড লিখুন"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"ভুল পিন কোড দেওয়া হয়েছে।"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ভুল কার্ড।"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"চার্জ হয়েছে"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ওয়্যারলেস পদ্ধতিতে চার্জ হচ্ছে"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • দ্রুত চার্জ হচ্ছে"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ধীরে চার্জ হচ্ছে"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • চার্জ করা সাময়িকভাবে বন্ধ রাখা হয়েছে"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"আপনার চার্জার সংযুক্ত করুন।"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"আনলক করতে মেনুতে টিপুন।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"নেটওয়ার্ক লক করা আছে"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"কোনো সিম কার্ড নেই"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"ডিভাইসের পাসওয়ার্ড"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"সিম পিন অঞ্চল"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"সিম PUK অঞ্চল"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"পরবর্তী অ্যালার্ম <xliff:g id="ALARM">%1$s</xliff:g> এ সেট করা হয়েছে"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"মুছুন"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"ই-সিমটি অক্ষম করুন"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"ই-সিম বন্ধ করা যাচ্ছে না"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"একটি সমস্যার কারণে ই-সিমটি বন্ধ করা যাচ্ছে না।"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"এন্টার"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"প্যাটার্ন ভুলে গেছি"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"ভুল প্যাটার্ন"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"ভুল পাসওয়ার্ড"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"ভুল পিন"</string>
@@ -68,12 +56,9 @@
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।</item>
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"আপনার প্যাটার্ন আঁকুন"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"সিমের পিন লিখুন।"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" এর জন্য সিমের পিন লিখুন।"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> মোবাইল পরিষেবা ছাড়া ডিভাইস ব্যবহার করার জন্য ই-সিম বন্ধ করুন।"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"পিন লিখুন"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"পাসওয়ার্ড লিখুন"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"সিমটি এখন অক্ষম করা হয়েছে। চালিয়ে যেতে PUK কোডটি লিখুন। বিশদ বিবরণের জন্য পরিষেবা প্রদানকারীর সাথে যোগাযোগ করুন।"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"সিম <xliff:g id="CARRIER">%1$s</xliff:g> এখন অক্ষম করা হয়েছে। চালিয়ে যেতে PUK কোডটি লিখুন। বিশদ বিবরণের জন্য পরিষেবা প্রদানকারীর সাথে যোগাযোগ করুন।"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"আপনার পছন্দের পিন কোড লিখুন"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"সিম কার্ড আনলক করা হচ্ছে…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"একটি ৪ থেকে ৮ সংখ্যার পিন লিখুন।"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK কোডটি ৮ বা তার বেশি সংখ্যার হতে হবে।"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"সঠিক PUK কোডটি পুনরায় লিখুন। বার বার চেষ্টা করা হলে সিমটি স্থায়ীভাবে অক্ষম হয়ে যাবে।"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"বিভিন্ন প্যাটার্নের সাহায্যে খুব বেশি বার প্রচেষ্টা করা হয়ে গেছে"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"আপনি আপনার পিন টাইপ করতে <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুল করেছেন৷ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন৷"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আপনার পাসওয়ার্ড লিখেছেন।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"আপনি <xliff:g id="NUMBER_0">%1$d</xliff:g> বার ভুলভাবে আপনার আনলকের প্যাটার্ন এঁকেছেন।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> সেকেন্ডের মধ্যে আবার চেষ্টা করুন।"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"সিম পিন দিয়ে আনলক করা যায়নি!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"সিম PUK দিয়ে আনলক করা যায়নি!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"কোড স্বীকৃত হয়েছে!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"কোনো পরিষেবা নেই।"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ইনপুট পদ্ধতি পরিবর্তন করুন"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"বিমান মোড"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ডিভাইসটি পুনরায় চালু হওয়ার পর প্যাটার্নের প্রয়োজন হবে"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"অতিরিক্ত সুরক্ষার জন্য প্যাটার্ন দেওয়া প্রয়োজন"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"অতিরিক্ত সুরক্ষার জন্য পিন দেওয়া প্রয়োজন"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"অতিরিক্ত সুরক্ষার জন্য পাসওয়ার্ড দেওয়া প্রয়োজন"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"আপনি প্রোফাইলগুলি স্যুইচ করার সময় প্যাটার্নের প্রয়োজন হবে"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"প্রোফাইলগুলি স্যুইচ করার সময় পিন প্রয়োজন হবে"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"আপনি প্রোফাইলগুলি স্যুইচ করার সময় পাসওয়ার্ডের প্রয়োজন হবে"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"প্রশাসক ডিভাইসটি লক করেছেন"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ডিভাইসটিকে ম্যানুয়ালি লক করা হয়েছে"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">ডিভাইসটি <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধরে আনলক করা হয় নি। প্যাটার্নটি নিশ্চিত করুন।</item>
-      <item quantity="other">ডিভাইসটি <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধরে আনলক করা হয় নি। প্যাটার্নটি নিশ্চিত করুন।</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">ডিভাইসটি <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধরে আনলক করা হয়নি। পিন নিশ্চিত করুন৷</item>
-      <item quantity="other">ডিভাইসটি <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধরে আনলক করা হয়নি। পিন নিশ্চিত করুন৷</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">ডিভাইসটি <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধরে আনলক করা হয় নি। পাসওয়ার্ড নিশ্চিত করুন।</item>
-      <item quantity="other">ডিভাইসটি <xliff:g id="NUMBER_1">%d</xliff:g> ঘণ্টা ধরে আনলক করা হয় নি। পাসওয়ার্ড নিশ্চিত করুন।</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"শনাক্ত করা যায়নি"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"শনাক্ত করা যায়নি"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-bs/strings.xml b/packages/SystemUI/res-keyguard/values-bs/strings.xml
index ab907be..ef15ce3 100644
--- a/packages/SystemUI/res-keyguard/values-bs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-bs/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Zaključavanje tastature"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Upišite PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Upišite PUK za SIM i novi PIN kôd"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK kôd za SIM karticu"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Novi PIN za SIM karticu"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Dodirnite da upišete lozinku"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Upišite lozinku za otključavanje"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Upišite PIN za otključavanje"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Unesite svoj PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Unesite uzorak"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Unesite lozinku"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Pogrešan PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Nevažeća kartica."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Napunjeno"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bežično punjenje"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Brzo punjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sporo punjenje"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je privremeno ograničeno"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite meni da otključate."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nema SIM kartice"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Lozinka uređaja"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Prostor za PIN za SIM karticu"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Prostor za PUK za SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Naredni alarm je podešen za <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Izbriši"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Onemogući eSIM karticu"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Nije moguće onemogućiti eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM nije moguće onemogućiti zbog greške."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Zaboravili ste uzorak?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Pogrešan uzorak"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Pogrešna lozinka"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Pogrešan PIN"</string>
@@ -69,12 +57,9 @@
       <item quantity="few">Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekunde.</item>
       <item quantity="other">Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekundi.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Nacrtajte uzorak"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Unesite PIN SIM kartice."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Unesite PIN SIM kartice operatera \"<xliff:g id="CARRIER">%1$s</xliff:g>\""</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Onemogućite eSIM za korištenje uređaja bez mobilne usluge."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Unesite PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Unesite lozinku"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM kartica je sada onemogućena. Unesite PUK kôd da nastavite. Za više informacija obratite se operateru."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Operater SIM kartice \"<xliff:g id="CARRIER">%1$s</xliff:g>\" sada je onemogućen. Unesite PUK kôd da nastavite. Za više informacija obratite se operateru."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Unesite željeni PIN"</string>
@@ -82,8 +67,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Otključavanje SIM kartice…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Unesite PIN koji sadrži 4 do 8 brojeva."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kôd treba sadržavati najmanje 8 brojeva."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Ponovo unesite ispravan PUK kôd. Ponovljeni pokušaji će trajno onemogućiti SIM karticu."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Previše puta ste pokušali otključati uređaj crtanjem uzorka"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Pogrešno ste unijeli PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Pogrešno ste unijeli lozinku <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Pogrešno ste nacrtali svoj uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> puta. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
@@ -101,8 +84,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Korištenje PIN-a za SIM karticu nije uspjelo!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Korištenje PUK-a za SIM nije uspjelo!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kôd je prihvaćen"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Nema mreže."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Promjena načina unosa"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Način rada u avionu"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Potreban je uzorak nakon što se uređaj ponovo pokrene"</string>
@@ -111,26 +92,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Uzorak je potreban radi dodatne sigurnosti"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN je potreban radi dodatne sigurnosti"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Lozinka je potrebna radi dodatne sigurnosti"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Potreban je uzorak nakon prelaska na drugi profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Potreban je PIN nakon prelaska na drugi profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Potrebna je lozinka nakon prelaska na drugi profil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Uređaj je zaključao administrator"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Uređaj je ručno zaključan"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sat. Potvrdite uzorak.</item>
-      <item quantity="few">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sata. Potvrdite uzorak.</item>
-      <item quantity="other">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite uzorak.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sat. Potvrdite PIN.</item>
-      <item quantity="few">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sata. Potvrdite PIN.</item>
-      <item quantity="other">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sat. Potvrdite lozinku.</item>
-      <item quantity="few">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sata. Potvrdite lozinku.</item>
-      <item quantity="other">Uređaj nije otključavan <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite lozinku.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nije prepoznato"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nije prepoznato"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ca/strings.xml b/packages/SystemUI/res-keyguard/values-ca/strings.xml
index 90b7a34..5a71f37 100644
--- a/packages/SystemUI/res-keyguard/values-ca/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ca/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Bloqueig de teclat"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Escriu el codi PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Escriu el PUK de la SIM i el codi PIN nou"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Codi PUK de la SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Codi PIN de la SIM nou"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Toca per escriure la contrasenya"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Escriu la contrasenya per desbloquejar"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Escriu el PIN per desbloquejar"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Introdueix el PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Introdueix el patró"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introdueix la contrasenya"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"El codi PIN no és correcte."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"La targeta no és vàlida."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Bateria carregada"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant sense fil"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant ràpidament"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • S\'està carregant lentament"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Càrrega limitada temporalment"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Connecta el carregador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prem Menú per desbloquejar."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"La xarxa està bloquejada"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"No hi ha cap SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Contrasenya del dispositiu"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Zona del PIN de la SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Zona del PUK de la SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"S\'ha configurat la propera alarma (<xliff:g id="ALARM">%1$s</xliff:g>)"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Suprimeix"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Desactiva l\'eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"No es pot desactivar l\'eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"S\'ha produït un error i no es pot desactivar l\'eSIM."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Retorn"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"He oblidat el patró"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Patró incorrecte"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Contrasenya incorrecta"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"El PIN no és correcte"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Torna-ho a provar d\'aquí a <xliff:g id="NUMBER">%d</xliff:g> segons.</item>
       <item quantity="one">Torna-ho a provar d\'aquí a 1 segon.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Dibuixa el patró"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Introdueix el PIN de la SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Introdueix el PIN de la SIM de: <xliff:g id="CARRIER">%1$s</xliff:g>."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desactiva l\'eSIM per utilitzar el dispositiu sense servei mòbil."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Introdueix el PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Introdueix la contrasenya"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"La SIM està desactivada. Introdueix el codi PUK per continuar. Contacta amb l\'operador de telefonia mòbil per obtenir més informació."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"La SIM <xliff:g id="CARRIER">%1$s</xliff:g> està desactivada. Introdueix el codi PUK per continuar. Contacta amb l\'operador de telefonia mòbil per obtenir més informació."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Introdueix el codi PIN que vulguis"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"S\'està desbloquejant la targeta SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Escriu un PIN que tingui entre 4 i 8 números."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"El codi PUK ha de tenir 8 números o més."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Torna a introduir el codi PUK correcte. Si ho intentes diverses vegades, es desactivarà la SIM permanentment."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Has intentat dibuixar el patró massa vegades"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Has escrit el PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Has escrit la contrasenya <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Has dibuixat el patró de desbloqueig <xliff:g id="NUMBER_0">%1$d</xliff:g> vegades de manera incorrecta. \n\nTorna-ho a provar d\'aquí a <xliff:g id="NUMBER_1">%2$d</xliff:g> segons."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Ha fallat l\'operació del PIN de la SIM"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"No s\'ha pogut desbloquejar la SIM amb el codi PUK."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"S\'ha acceptat el codi."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Sense servei"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Canvia el mètode d\'introducció"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Mode d\'avió"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Cal introduir el patró quan es reinicia el dispositiu"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Cal introduir el patró per disposar de més seguretat"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Cal introduir el PIN per disposar de més seguretat"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Cal introduir la contrasenya per disposar de més seguretat"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Cal introduir el patró en canviar de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Cal introduir el PIN en canviar de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Cal introduir la contrasenya en canviar de perfil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"L\'administrador ha bloquejat el dispositiu"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"El dispositiu s\'ha bloquejat manualment"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Fa <xliff:g id="NUMBER_1">%d</xliff:g> hores que no es desbloqueja el dispositiu. Confirma el patró.</item>
-      <item quantity="one">Fa <xliff:g id="NUMBER_0">%d</xliff:g> hora que no es desbloqueja el dispositiu. Confirma el patró.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Fa <xliff:g id="NUMBER_1">%d</xliff:g> hores que no es desbloqueja el dispositiu. Confirma el PIN.</item>
-      <item quantity="one">Fa <xliff:g id="NUMBER_0">%d</xliff:g> hora que no es desbloqueja el dispositiu. Confirma el PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Fa <xliff:g id="NUMBER_1">%d</xliff:g> hores que no es desbloqueja el dispositiu. Confirma la contrasenya.</item>
-      <item quantity="one">Fa <xliff:g id="NUMBER_0">%d</xliff:g> hora que no es desbloqueja el dispositiu. Confirma la contrasenya.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"No s\'ha reconegut"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"No s\'ha reconegut"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-cs/strings.xml b/packages/SystemUI/res-keyguard/values-cs/strings.xml
index ddfbeaf..41300fc 100644
--- a/packages/SystemUI/res-keyguard/values-cs/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-cs/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Uzamknutí"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Zadejte kód PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Zadejte kód PUK SIM karty a nový kód PIN"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Kód PUK SIM karty"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nový PIN SIM karty"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Klepnutím zadáte heslo"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Zadejte heslo pro odemknutí"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Zadejte kód PIN pro odemknutí"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Zadejte PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Zadejte gesto"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Zadejte heslo"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Nesprávný kód PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Neplatná karta."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Nabito"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bezdrátové nabíjení"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Rychlé nabíjení"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pomalé nabíjení"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjení je dočasně omezeno"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Připojte dobíjecí zařízení."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Klávesy odemknete stisknutím tlačítka nabídky."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Síť je blokována"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Chybí SIM karta"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Heslo zařízení"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Oblast kódu PIN SIM karty"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Oblast kódu PUK SIM karty"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Další budík je nastaven na <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Smazat"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Deaktivovat eSIM kartu"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Nelze deaktivovat eSIM kartu"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM kartu kvůli chybě nelze deaktivovat."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Zapomenuté gesto"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Nesprávné gesto"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Špatné heslo"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Nesprávný kód PIN"</string>
@@ -70,12 +58,9 @@
       <item quantity="other">Zkuste to znovu za <xliff:g id="NUMBER">%d</xliff:g> sekund.</item>
       <item quantity="one">Zkuste to znovu za 1 sekundu.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Zadejte gesto"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Zadejte kód PIN SIM karty."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Zadejte kód PIN SIM karty <xliff:g id="CARRIER">%1$s</xliff:g>."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> eSIM kartu deaktivujte, chcete-li zařízení používat bez mobilních služeb."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Zadejte kód PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Zadejte heslo"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM karta byla zablokována. Chcete-li pokračovat, je třeba zadat kód PUK. Podrobné informace získáte od operátora."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM karta <xliff:g id="CARRIER">%1$s</xliff:g> je teď zablokována. Chcete-li pokračovat, zadejte kód PUK. Podrobnosti vám poskytne operátor."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Zadejte požadovaný kód PIN"</string>
@@ -83,8 +68,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Odblokování SIM karty…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Zadejte kód PIN o délce 4–8 číslic."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Minimální délka kódu PUK je 8 číslic."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Znovu zadejte správný kód PUK. Opakovanými pokusy SIM kartu trvale zablokujete."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Příliš mnoho pokusů o zadání gesta"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste zadali nesprávný kód PIN. \n\nZkuste to znovu za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste nesprávně zadali heslo. \n\nZkuste to znovu za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Již <xliff:g id="NUMBER_0">%1$d</xliff:g>krát jste zadali nesprávné bezpečnostní gesto. \n\nZkuste to znovu za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
@@ -104,8 +87,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Operace pomocí kódu PIN SIM karty se nezdařila."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Operace pomocí kódu PUK SIM karty se nezdařila."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kód byl přijat."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Žádný signál"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Přepnout metodu zadávání"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Režim Letadlo"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Po restartování zařízení je vyžadováno gesto"</string>
@@ -114,29 +95,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pro ještě lepší zabezpečení je vyžadováno gesto"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Pro ještě lepší zabezpečení je vyžadován kód PIN"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Pro ještě lepší zabezpečení je vyžadováno heslo"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Po přepnutí profilů je vyžadováno gesto"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Po přepnutí profilů je vyžadován kód PIN"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Po přepnutí profilů je vyžadováno heslo"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Zařízení je uzamknuto administrátorem"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Zařízení bylo ručně uzamčeno"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="few">Zařízení již <xliff:g id="NUMBER_1">%d</xliff:g> hodiny nebylo odemknuto. Zadejte gesto.</item>
-      <item quantity="many">Zařízení již <xliff:g id="NUMBER_1">%d</xliff:g> hodiny nebylo odemknuto. Zadejte gesto.</item>
-      <item quantity="other">Zařízení již <xliff:g id="NUMBER_1">%d</xliff:g> hodin nebylo odemknuto. Zadejte gesto.</item>
-      <item quantity="one">Zařízení již <xliff:g id="NUMBER_0">%d</xliff:g> hodinu nebylo odemknuto. Zadejte gesto.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="few">Zařízení již <xliff:g id="NUMBER_1">%d</xliff:g> hodiny nebylo odemknuto. Zadejte PIN.</item>
-      <item quantity="many">Zařízení již <xliff:g id="NUMBER_1">%d</xliff:g> hodiny nebylo odemknuto. Zadejte PIN.</item>
-      <item quantity="other">Zařízení již <xliff:g id="NUMBER_1">%d</xliff:g> hodin nebylo odemknuto. Zadejte PIN.</item>
-      <item quantity="one">Zařízení již <xliff:g id="NUMBER_0">%d</xliff:g> hodinu nebylo odemknuto. Zadejte PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="few">Zařízení již <xliff:g id="NUMBER_1">%d</xliff:g> hodiny nebylo odemknuto. Zadejte heslo.</item>
-      <item quantity="many">Zařízení již <xliff:g id="NUMBER_1">%d</xliff:g> hodiny nebylo odemknuto. Zadejte heslo.</item>
-      <item quantity="other">Zařízení již <xliff:g id="NUMBER_1">%d</xliff:g> hodin nebylo odemknuto. Zadejte heslo.</item>
-      <item quantity="one">Zařízení již <xliff:g id="NUMBER_0">%d</xliff:g> hodinu nebylo odemknuto. Zadejte heslo.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nerozpoznáno"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nerozpoznáno"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-da/strings.xml b/packages/SystemUI/res-keyguard/values-da/strings.xml
index 8b686d7..01ea136 100644
--- a/packages/SystemUI/res-keyguard/values-da/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-da/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Nøglebeskyttelse"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Angiv pinkoden"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Angiv PUK-koden og den nye pinkode til SIM-kortet"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK-kode til SIM-kort"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Ny pinkode til SIM-kortet"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Tryk for at angive adgangskode"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Angiv adgangskoden for at låse op"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Angiv pinkoden for at låse op"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Angiv din pinkode"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Angiv dit mønster"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Angiv din adgangskode"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Forkert pinkode."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ugyldigt kort."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Opladet"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Trådløs opladning"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader hurtigt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Oplader langsomt"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladningen er midlertidigt begrænset"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Tilslut din oplader."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tryk på menuen for at låse op."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netværket er låst"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Intet SIM-kort"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Adgangskode til enhed"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Område for pinkoden til SIM-kortet"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Område for PUK-koden til SIM-kortet"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Næste alarm er indstillet til <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Slet"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Deaktiver eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM kan ikke deaktiveres"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM kan ikke deaktiveres på grund af en fejl."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Har du glemt mønsteret?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Forkert mønster"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Forkert adgangskode"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Forkert pinkode"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">Prøv igen om <xliff:g id="NUMBER">%d</xliff:g> sekund.</item>
       <item quantity="other">Prøv igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Tegn dit mønster"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Angiv pinkoden til SIM-kortet."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Angiv pinkoden til SIM-kortet fra \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Deaktiver eSIM for at bruge enheden uden mobiltjeneste."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Angiv pinkode"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Angiv adgangskode"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM-kortet er nu deaktiveret. Angiv PUK-koden for at fortsætte. Kontakt mobilselskabet for at få flere oplysninger."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM-kortet fra \"<xliff:g id="CARRIER">%1$s</xliff:g>\" er nu deaktiveret. Angiv PUK-koden for at fortsætte. Kontakt mobilselskabet for at få flere oplysninger."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Angiv den ønskede pinkode"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Låser SIM-kortet op…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Angiv en pinkode på mellem 4 og 8 tal."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-koden skal være på 8 tal eller mere."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Angiv den korrekte PUK-kode. Gentagne forsøg deaktiverer permanent SIM-kortet."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Du har brugt for mange forsøg på at tegne mønsteret korrekt"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Du har indtastet en forkert pinkode <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. \n\nPrøv igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Du har indtastet din adgangskode forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. \n\nPrøv igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Du har tegnet dit oplåsningsmønster forkert <xliff:g id="NUMBER_0">%1$d</xliff:g> gange. \n\nPrøv igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Pinkoden til SIM-kortet blev afvist"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"PUK-koden til SIM-kortet blev afvist"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Koden blev accepteret."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Ingen dækning."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Skift indtastningsmetode"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Flytilstand"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Du skal angive et mønster, når du har genstartet enheden"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Der kræves et mønster som ekstra beskyttelse"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Der kræves en pinkode som ekstra beskyttelse"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Der kræves en adgangskode som ekstra beskyttelse"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Du skal angive et mønster, når du skifter profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Der skal angives en pinkode, når du skifter profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Der skal angives en adgangskode, når du skifter profil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Enheden er blevet låst af administratoren"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Enheden blev låst manuelt"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Enheden blev sidst låst op for <xliff:g id="NUMBER_1">%d</xliff:g> time siden. Bekræft mønsteret.</item>
-      <item quantity="other">Enheden blev sidst låst op for <xliff:g id="NUMBER_1">%d</xliff:g> timer siden. Bekræft mønsteret.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Enheden blev sidst låst op for <xliff:g id="NUMBER_1">%d</xliff:g> time siden. Bekræft pinkoden.</item>
-      <item quantity="other">Enheden blev sidst låst op for <xliff:g id="NUMBER_1">%d</xliff:g> timer siden. Bekræft pinkoden.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Enheden blev sidst låst op for <xliff:g id="NUMBER_1">%d</xliff:g> time siden. Bekræft adgangskoden.</item>
-      <item quantity="other">Enheden blev sidst låst op for <xliff:g id="NUMBER_1">%d</xliff:g> timer siden. Bekræft adgangskoden.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Ikke genkendt"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ikke genkendt"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-de/strings.xml b/packages/SystemUI/res-keyguard/values-de/strings.xml
index 5be92983..0d6728a 100644
--- a/packages/SystemUI/res-keyguard/values-de/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-de/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Bitte gib den PIN-Code ein"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Gib den PUK-Code der SIM-Karte und den neuen PIN-Code ein"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK-Code der SIM-Karte"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Neuer PIN-Code der SIM-Karte"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Zur Passworteingabe berühren"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Bitte gib das Passwort zum Entsperren ein"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Bitte gib die PIN zum Entsperren ein"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Gib deine PIN ein"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Muster eingeben"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Passwort eingeben"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Falscher PIN-Code."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ungültige Karte."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Aufgeladen"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kabelloses Laden"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird schnell geladen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wird langsam geladen"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laden vorübergehend eingeschränkt"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Ladegerät anschließen."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Zum Entsperren die Menütaste drücken."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netzwerk gesperrt"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Keine SIM-Karte"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Gerätepasswort"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM-PIN-Bereich"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM-PUK-Bereich"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Nächster Weckruf eingerichtet für <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Löschen"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM deaktivieren"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Die eSIM kann nicht deaktiviert werden"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Die eSim kann aufgrund eines Fehlers nicht deaktiviert werden."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Eingabe"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Muster vergessen"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Falsches Muster"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Falsches Passwort"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Falsche PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">In <xliff:g id="NUMBER">%d</xliff:g> Sekunden noch einmal versuchen.</item>
       <item quantity="one">In 1 Sekunde noch einmal versuchen.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Muster zeichnen"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Gib die SIM-PIN ein"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Gib die SIM-PIN für \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ein."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Deaktiviere die eSIM, um das Gerät ohne Mobilfunkdienst zu verwenden."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"PIN eingeben"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Passwort eingeben"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Die SIM-Karte ist jetzt deaktiviert. Gib den PUK-Code ein, um fortzufahren. Weitere Informationen erhältst du von deinem Mobilfunkanbieter."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Die SIM-Karte \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ist jetzt deaktiviert. Gib den PUK-Code ein, um fortzufahren. Weitere Informationen erhältst du von deinem Mobilfunkanbieter."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Gewünschten PIN-Code eingeben"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM-Karte wird entsperrt..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Gib eine 4- bis 8-stellige PIN ein."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Der PUK-Code muss mindestens 8 Ziffern aufweisen."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Gib den richtigen PUK-Code ein. Bei wiederholten Versuchen wird die SIM-Karte dauerhaft deaktiviert."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Zu viele Musterversuche"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Du hast deine PIN <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch eingegeben.\n\nBitte versuche es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Du hast dein Passwort <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch eingegeben.\n\nBitte versuche es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Du hast dein Entsperrungsmuster <xliff:g id="NUMBER_0">%1$d</xliff:g>-mal falsch gezeichnet. \n\nBitte versuche es in <xliff:g id="NUMBER_1">%2$d</xliff:g> Sekunden noch einmal."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Fehler beim Entsperren der SIM-Karte mit der PIN."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Fehler beim Entsperren der SIM-Karte mithilfe des PUK-Codes."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Code akzeptiert."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Dienst nicht verfügbar"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Eingabemethode wechseln"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Flugmodus"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Nach dem Neustart des Geräts ist die Eingabe des Musters erforderlich"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Zur Verbesserung der Sicherheit ist ein Muster erforderlich"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Zur Verbesserung der Sicherheit ist eine PIN erforderlich"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Zur Verbesserung der Sicherheit ist ein Passwort erforderlich"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Beim Profilwechsel ist die Eingabe des Musters erforderlich"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Beim Profilwechsel ist die Eingabe der PIN erforderlich"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Beim Profilwechsel ist die Eingabe des Passworts erforderlich"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Gerät vom Administrator gesperrt"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Gerät manuell gesperrt"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Das Gerät wurde seit <xliff:g id="NUMBER_1">%d</xliff:g> Stunden nicht mehr entsperrt. Bitte bestätige das Muster.</item>
-      <item quantity="one">Das Gerät wurde seit <xliff:g id="NUMBER_0">%d</xliff:g> Stunde nicht mehr entsperrt. Bitte bestätige das Muster.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Das Gerät wurde seit <xliff:g id="NUMBER_1">%d</xliff:g> Stunden nicht mehr entsperrt. Bitte bestätige die PIN.</item>
-      <item quantity="one">Das Gerät wurde seit <xliff:g id="NUMBER_0">%d</xliff:g> Stunde nicht mehr entsperrt. Bitte bestätige die PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Das Gerät wurde seit <xliff:g id="NUMBER_1">%d</xliff:g> Stunden nicht mehr entsperrt. Bitte bestätige das Passwort.</item>
-      <item quantity="one">Das Gerät wurde seit <xliff:g id="NUMBER_0">%d</xliff:g> Stunde nicht mehr entsperrt. Bitte bestätige das Passwort.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nicht erkannt"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nicht erkannt"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-el/strings.xml b/packages/SystemUI/res-keyguard/values-el/strings.xml
index 4e8250f..518f2e2 100644
--- a/packages/SystemUI/res-keyguard/values-el/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-el/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Πληκτρολογήστε τον κωδικό PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Πληκτρολογήστε τον κωδικό PUK της κάρτας SIM και τον νέο κωδικό PIN"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Κωδικός PUK κάρτας SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Νέος κωδικός PIN της κάρτας SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Αγγίξτε για εισαγ. κωδ. πρόσβ."</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Πληκτρολογήστε τον κωδικό πρόσβασης για ξεκλείδωμα"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Πληκτρολογήστε τον αριθμό PIN για ξεκλείδωμα"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Εισαγάγετε τον αριθμό PIN σας"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Εισαγάγετε το μοτίβο σας"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Εισαγάγετε κωδικό πρόσβασης"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Λανθασμένος κωδικός PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Μη έγκυρη κάρτα."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Φορτίστηκε"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ασύρματη φόρτιση"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Γρήγορη φόρτιση"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Αργή φόρτιση"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Προσωρινός περιορισμός φόρτισης"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Συνδέστε τον φορτιστή."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Πατήστε \"Μενού\" για ξεκλείδωμα."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Κλειδωμένο δίκτυο"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Δεν υπάρχει SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Κωδικός πρόσβασης συσκευής"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Περιοχή αριθμού PIN κάρτας SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Περιοχή κωδικού PUK κάρτας SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Το επόμενο ξυπνητήρι ορίστηκε στις <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Διαγραφή"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Απενεργοποίηση eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Αδυναμία απενεργοποίησης eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Δεν είναι δυνατή η απενεργοποίηση της eSIM, εξαιτίας κάποιου σφάλματος."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Ξεχάσατε το μοτίβο"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Λανθασμένο μοτίβο"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Λανθασμένος κωδικός πρόσβασης"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Λανθασμένο PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Δοκιμάστε ξανά σε <xliff:g id="NUMBER">%d</xliff:g> δευτερόλεπτα.</item>
       <item quantity="one">Δοκιμάστε ξανά σε 1 δευτερόλεπτο.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Σχεδιάστε το μοτίβο σας"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Εισαγωγή αριθμού PIN κάρτας SIM"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Εισαγάγετε τον αριθμό PIN της κάρτας SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Απενεργοποιήστε την eSIM, για να χρησιμοποιήσετε τη συσκευή χωρίς υπηρεσία για κινητά."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Εισαγάγετε τον αριθμό PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Εισαγάγετε κωδικό πρόσβασης"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Η κάρτα SIM είναι απενεργοποιημένη αυτή τη στιγμή. Εισαγάγετε τον κωδικό PUK για να συνεχίσετε. Επικοινωνήστε με την εταιρεία κινητής τηλεφωνίας σας για λεπτομέρειες."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Η SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" έχει απενεργοποιηθεί. Εισάγετε τον κωδικό PUK για συνέχεια. Επικοινωνήστε με την εταιρεία κινητής τηλεφωνίας για λεπτομέρειες."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Εισαγάγετε τον απαιτούμενο κωδικό PIN"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Ξεκλείδωμα κάρτας SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Πληκτρολογήστε έναν αριθμό PIN που να αποτελείται από 4 έως 8 αριθμούς."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Ο κωδικός PUK θα πρέπει να περιέχει τουλάχιστον 8 αριθμούς."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Εισαγάγετε ξανά τον κωδικό PUK. Οι επαναλαμβανόμενες προσπάθειες θα απενεργοποιήσουν οριστικά την κάρτα SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Πάρα πολλές προσπάθειες μοτίβου!"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Έχετε πληκτρολογήσει τον αριθμό PIN εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. \n\nΠροσπαθήστε ξανά σε <xliff:g id="NUMBER_1">%2$d</xliff:g> δευτερόλεπτα."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Έχετε πληκτρολογήσει τον κωδικό πρόσβασης εσφαλμένα <xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. \n\nΠροσπαθήστε ξανά σε <xliff:g id="NUMBER_1">%2$d</xliff:g> δευτερόλεπτα."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Σχεδιάσατε εσφαλμένα το μοτίβο ξεκλειδώματος<xliff:g id="NUMBER_0">%1$d</xliff:g> φορές. \n\nΠροσπαθήστε ξανά σε <xliff:g id="NUMBER_1">%2$d</xliff:g> δευτερόλεπτα."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Αποτυχία λειτουργίας κωδικού PIN κάρτας SIM!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Αποτυχία λειτουργίας κωδικού PUK κάρτας SIM!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Αποδεκτός κωδικός!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Καμία υπηρεσία."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Εναλλαγή μεθόδου εισαγωγής"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Λειτουργία πτήσης"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Απαιτείται μοτίβο μετά από την επανεκκίνηση της συσκευής"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Απαιτείται μοτίβο για πρόσθετη ασφάλεια"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Απαιτείται PIN για πρόσθετη ασφάλεια"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Απαιτείται κωδικός πρόσβασης για πρόσθετη ασφάλεια"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Απαιτείται μοτίβο κατά την εναλλαγή προφίλ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Απαιτείται PIN κατά την εναλλαγή προφίλ"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Απαιτείται κωδικός πρόσβασης κατά την εναλλαγή προφίλ"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Η συσκευή κλειδώθηκε από τον διαχειριστή"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Η συσκευή κλειδώθηκε με μη αυτόματο τρόπο"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Η συσκευή δεν έχει ξεκλειδωθεί εδώ και <xliff:g id="NUMBER_1">%d</xliff:g> ώρες. Επιβεβαιώστε το μοτίβο.</item>
-      <item quantity="one">Η συσκευή δεν έχει ξεκλειδωθεί εδώ και <xliff:g id="NUMBER_0">%d</xliff:g> ώρα. Επιβεβαιώστε το μοτίβο.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Η συσκευή δεν έχει ξεκλειδωθεί εδώ και <xliff:g id="NUMBER_1">%d</xliff:g> ώρες. Επιβεβαιώστε τον αριθμό PIN.</item>
-      <item quantity="one">Η συσκευή δεν έχει ξεκλειδωθεί εδώ και <xliff:g id="NUMBER_0">%d</xliff:g> ώρα. Επιβεβαιώστε τον αριθμό PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Η συσκευή δεν έχει ξεκλειδωθεί εδώ και <xliff:g id="NUMBER_1">%d</xliff:g> ώρες. Επιβεβαιώστε τον κωδικό πρόσβασης.</item>
-      <item quantity="one">Η συσκευή δεν έχει ξεκλειδωθεί εδώ και <xliff:g id="NUMBER_0">%d</xliff:g> ώρα. Επιβεβαιώστε τον κωδικό πρόσβασης.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Δεν αναγνωρίστηκε"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Δεν αναγνωρίστηκε"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
index 009b7cb..e2db3b1 100644
--- a/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rAU/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Type PIN code"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Type SIM PUK and new PIN code"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK code"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"New SIM PIN code"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Touch to type password"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Type password to unlock"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Type PIN to unlock"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Enter your PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Enter your pattern"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Enter your password"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Invalid card."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Charged"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging temporarily limited"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"No SIM card"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Device password"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN area"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK area"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Next alarm set for <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Delete"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Disable eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Can’t disable eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"The eSIM can’t be disabled due to an error."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Forgotten Pattern"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Wrong pattern"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Wrong password"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Wrong PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
       <item quantity="one">Try again in 1 second.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Draw your pattern"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Enter SIM PIN."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Enter SIM PIN for \'<xliff:g id="CARRIER">%1$s</xliff:g>\'."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disable eSIM to use device without mobile service."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Enter PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Enter Password"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Enter desired PIN code"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Unlocking SIM card…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Type a PIN that is 4 to 8 numbers."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK code should be 8 numbers or more."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Re-enter the correct PUK code. Repeated attempts will permanently disable the SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Too many pattern attempts"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"You have incorrectly typed your PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"You have incorrectly typed your password <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN operation failed!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK operation failed!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Code accepted"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"No service"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Switch input method"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Aeroplane mode"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pattern required after device restarts"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pattern required for additional security"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN required for additional security"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Password required for additional security"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Pattern required when you switch profiles"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PIN required when you switch profiles"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Password required when you switch profiles"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Device locked by admin"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Device was locked manually"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm pattern.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm pattern.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm PIN.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm password.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm password.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Not recognised"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Not recognised"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
index 21f32cf..6c9ddb8 100644
--- a/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rCA/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Type PIN code"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Type SIM PUK and new PIN code"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK code"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"New SIM PIN code"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Touch to type password"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Type password to unlock"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Type PIN to unlock"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Enter your PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Enter your pattern"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Enter your password"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Invalid card."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Charged"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging temporarily limited"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"No SIM card"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Device password"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN area"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK area"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Next alarm set for <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Delete"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Disable eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Can’t disable eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"The eSIM can’t be disabled due to an error."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Forgotten Pattern"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Wrong pattern"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Wrong password"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Wrong PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
       <item quantity="one">Try again in 1 second.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Draw your pattern"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Enter SIM PIN."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Enter SIM PIN for \'<xliff:g id="CARRIER">%1$s</xliff:g>\'."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disable eSIM to use device without mobile service."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Enter PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Enter Password"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Enter desired PIN code"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Unlocking SIM card…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Type a PIN that is 4 to 8 numbers."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK code should be 8 numbers or more."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Re-enter the correct PUK code. Repeated attempts will permanently disable the SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Too many pattern attempts"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"You have incorrectly typed your PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"You have incorrectly typed your password <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN operation failed!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK operation failed!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Code accepted"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"No service"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Switch input method"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Airplane mode"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pattern required after device restarts"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pattern required for additional security"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN required for additional security"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Password required for additional security"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Pattern required when you switch profiles"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PIN required when you switch profiles"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Password required when you switch profiles"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Device locked by admin"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Device was locked manually"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm pattern.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm pattern.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm PIN.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm password.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm password.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Not recognised"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Not recognised"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
index 009b7cb..e2db3b1 100644
--- a/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rGB/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Type PIN code"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Type SIM PUK and new PIN code"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK code"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"New SIM PIN code"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Touch to type password"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Type password to unlock"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Type PIN to unlock"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Enter your PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Enter your pattern"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Enter your password"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Invalid card."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Charged"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging temporarily limited"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"No SIM card"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Device password"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN area"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK area"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Next alarm set for <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Delete"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Disable eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Can’t disable eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"The eSIM can’t be disabled due to an error."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Forgotten Pattern"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Wrong pattern"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Wrong password"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Wrong PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
       <item quantity="one">Try again in 1 second.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Draw your pattern"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Enter SIM PIN."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Enter SIM PIN for \'<xliff:g id="CARRIER">%1$s</xliff:g>\'."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disable eSIM to use device without mobile service."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Enter PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Enter Password"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Enter desired PIN code"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Unlocking SIM card…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Type a PIN that is 4 to 8 numbers."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK code should be 8 numbers or more."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Re-enter the correct PUK code. Repeated attempts will permanently disable the SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Too many pattern attempts"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"You have incorrectly typed your PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"You have incorrectly typed your password <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN operation failed!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK operation failed!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Code accepted"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"No service"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Switch input method"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Aeroplane mode"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pattern required after device restarts"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pattern required for additional security"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN required for additional security"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Password required for additional security"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Pattern required when you switch profiles"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PIN required when you switch profiles"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Password required when you switch profiles"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Device locked by admin"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Device was locked manually"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm pattern.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm pattern.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm PIN.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm password.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm password.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Not recognised"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Not recognised"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
index 009b7cb..e2db3b1 100644
--- a/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rIN/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Type PIN code"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Type SIM PUK and new PIN code"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK code"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"New SIM PIN code"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Touch to type password"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Type password to unlock"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Type PIN to unlock"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Enter your PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Enter your pattern"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Enter your password"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Incorrect PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Invalid card."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Charged"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging wirelessly"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging rapidly"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging slowly"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Charging temporarily limited"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Connect your charger."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Press Menu to unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Network locked"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"No SIM card"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Device password"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN area"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK area"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Next alarm set for <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Delete"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Disable eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Can’t disable eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"The eSIM can’t be disabled due to an error."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Forgotten Pattern"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Wrong pattern"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Wrong password"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Wrong PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
       <item quantity="one">Try again in 1 second.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Draw your pattern"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Enter SIM PIN."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Enter SIM PIN for \'<xliff:g id="CARRIER">%1$s</xliff:g>\'."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disable eSIM to use device without mobile service."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Enter PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Enter Password"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" is now disabled. Enter PUK code to continue. Contact operator for details."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Enter desired PIN code"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Unlocking SIM card…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Type a PIN that is 4 to 8 numbers."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK code should be 8 numbers or more."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Re-enter the correct PUK code. Repeated attempts will permanently disable the SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Too many pattern attempts"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"You have incorrectly typed your PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"You have incorrectly typed your password <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%1$d</xliff:g> times. \n\nTry again in <xliff:g id="NUMBER_1">%2$d</xliff:g> seconds."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN operation failed!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK operation failed!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Code accepted"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"No service"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Switch input method"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Aeroplane mode"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pattern required after device restarts"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pattern required for additional security"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN required for additional security"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Password required for additional security"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Pattern required when you switch profiles"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PIN required when you switch profiles"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Password required when you switch profiles"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Device locked by admin"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Device was locked manually"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm pattern.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm pattern.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm PIN.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Device hasn\'t been unlocked for <xliff:g id="NUMBER_1">%d</xliff:g> hours. Confirm password.</item>
-      <item quantity="one">Device hasn\'t been unlocked for <xliff:g id="NUMBER_0">%d</xliff:g> hour. Confirm password.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Not recognised"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Not recognised"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
index a2d0bb7..9c32604 100644
--- a/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-en-rXC/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‎Keyguard‎‏‎‎‏‎"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‏‏‏‏‏‎‏‏‏‎‏‏‏‎‎‏‏‏‏‎Type PIN code‎‏‎‎‏‎"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‎‏‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‎‎Type SIM PUK and new PIN code‎‏‎‎‏‎"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‏‎SIM PUK code‎‏‎‎‏‎"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‎‏‎‏‎‎‏‏‏‏‎‎‏‎‏‏‎‎‏‏‎‏‎New SIM PIN code‎‏‎‎‏‎"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‎‏‏‎"<font size="17">"‎‏‎‎‏‏‏‎Touch to type password‎‏‎‎‏‏‎"</font>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‎‎‏‏‎‎‏‎Type password to unlock‎‏‎‎‏‎"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‏‏‏‏‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎‏‏‎‏‎Type PIN to unlock‎‏‎‎‏‎"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‏‏‎‎‏‎‏‎‏‏‏‏‏‎‏‎‎‏‎‎‏‏‏‎‏‏‎‎‎‎‎Enter your PIN‎‏‎‎‏‎"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‏‎‏‏‎‎‎‎‏‏‏‎‎‎‏‎‎‏‎Enter your pattern‎‏‎‎‏‎"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‎‎‏‏‎‏‎Enter your password‎‏‎‎‏‎"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‏‎‏‏‎‎Incorrect PIN code.‎‏‎‎‏‎"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‎Invalid Card.‎‏‎‎‏‎"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‎‏‎‎‏‎‏‏‏‎‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎‏‏‎Charged‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎‎‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging wirelessly‎‏‎‎‏‎"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‏‎‎‎‎‎‎‏‎‏‎‎‎‎‎‎‎‏‎‏‎‏‏‎‏‎‏‏‏‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging rapidly‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging slowly‎‏‎‎‏‎"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‎‎‏‎‏‎‏‎‎‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%s</xliff:g>‎‏‎‎‏‏‏‎ • Charging temporarily limited‎‏‎‎‏‎"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‎‏‎‏‏‏‏‏‏‎‎‎‎Connect your charger.‎‏‎‎‏‎"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‏‎‏‎‎Press Menu to unlock.‎‏‎‎‏‎"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‎‎‏‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‎‎‎‎‎Network locked‎‏‎‎‏‎"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‏‎‏‎‏‏‎‏‎‏‎‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‎‎‏‎‎‏‏‎‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎No SIM card‎‏‎‎‏‎"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‏‎‏‎‎Device password‎‏‎‎‏‎"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‏‎‎‎‎‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‏‏‏‏‏‎‎SIM PIN area‎‏‎‎‏‎"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‎‏‏‎‏‏‎‎‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‎SIM PUK area‎‏‎‎‏‎"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎Next alarm set for ‎‏‎‎‏‏‎<xliff:g id="ALARM">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎Delete‎‏‎‎‏‎"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎Disable eSIM‎‏‎‎‏‎"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‏‏‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‏‏‎Can’t disable eSIM‎‏‎‎‏‎"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‎‎‎‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎‎‎‏‏‎‎‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎‏‎‏‏‏‏‏‎The eSIM can’t be disabled due to an error.‎‏‎‎‏‎"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‎‎‏‎‎‏‏‎‎‎‎‏‎‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‎‎Enter‎‏‎‎‏‎"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‎‎‎‎‏‏‎‎‏‎‎‏‎‎‏‎‎‏‏‏‎‏‎‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎Forgot Pattern‎‏‎‎‏‎"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‏‎‏‏‏‎‏‎‎‎‎‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‎‎‏‏‏‎‏‎‎Wrong pattern‎‏‎‎‏‎"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎Wrong password‎‏‎‎‏‎"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‏‏‏‎‎‎‎‏‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‎Wrong PIN‎‏‎‎‏‎"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER">%d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎</item>
       <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‏‏‎‎‎‎‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‏‎‏‎‎Try again in 1 second.‎‏‎‎‏‎</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‏‏‎‏‏‏‎‎‎‎‏‎‎‏‏‏‎‏‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‏‎‎‎‎Draw your pattern‎‏‎‎‏‎"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎Enter SIM PIN.‎‏‎‎‏‎"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‎‎‏‎‎‏‎‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‎‎‏‎‎‎‏‎Enter SIM PIN for \"‎‏‎‎‏‏‎<xliff:g id="CARRIER">%1$s</xliff:g>‎‏‎‎‏‏‏‎\".‎‏‎‎‏‎"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‏‏‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‎‏‏‏‎‎‎‎‏‎‏‎‏‏‏‏‎‎‏‏‏‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g>‎‏‎‎‏‏‏‎ Disable eSIM to use device without mobile service.‎‏‎‎‏‎"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‏‏‎‏‎‎‏‏‎‎‏‎‏‏‎‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎Enter PIN‎‏‎‎‏‎"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‏‎‎‏‎‎‎‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎Enter Password‎‏‎‎‏‎"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‏‏‎‏‏‎‏‏‏‎‏‏‎‏‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‎‎‏‎‎‏‎‎‏‏‎‏‎‎‏‎SIM is now disabled. Enter PUK code to continue. Contact carrier for details.‎‏‎‎‏‎"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‏‏‎‏‏‎‏‏‏‏‏‎SIM \"‎‏‎‎‏‏‎<xliff:g id="CARRIER">%1$s</xliff:g>‎‏‎‎‏‏‏‎\" is now disabled. Enter PUK code to continue. Contact carrier for details.‎‏‎‎‏‎"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‏‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‏‏‏‏‏‏‏‎Enter desired PIN code‎‏‎‎‏‎"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‎‎‏‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‏‏‎‎‎‏‎‏‎‎‏‎‏‏‎‏‏‎‎Unlocking SIM card…‎‏‎‎‏‎"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‎‎Type a PIN that is 4 to 8 numbers.‎‏‎‎‏‎"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎PUK code should be 8 numbers or more.‎‏‎‎‏‎"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎Re-enter the correct PUK code. Repeated attempts will permanently disable the SIM.‎‏‎‎‏‎"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎‎‏‎‎‏‎‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‎Too many pattern attempts‎‏‎‎‏‎"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‏‏‏‎‎‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‏‏‎‏‏‎You have incorrectly typed your PIN ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‏‎‏‏‎‎You have incorrectly typed your password ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‏‏‎‏‎‏‏‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‎‎‎‎‎You have incorrectly drawn your unlock pattern ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%1$d</xliff:g>‎‏‎‎‏‏‏‎ times. ‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎‎‏‎‎‏‏‎\n‎‏‎‎‏‏‏‎Try again in ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%2$d</xliff:g>‎‏‎‎‏‏‏‎ seconds.‎‏‎‎‏‎"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎SIM PIN operation failed!‎‏‎‎‏‎"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‎‎SIM PUK operation failed!‎‏‎‎‏‎"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‏‎‏‏‎‏‎‏‎‏‎‎‎Code Accepted!‎‏‎‎‏‎"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‏‎‏‎‎No service.‎‏‎‎‏‎"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‎‎‎‏‎‎‏‏‎‎‎‎‏‏‎‏‎‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‎‏‎‏‎‎‎‏‎‎‎‏‎Switch input method‎‏‎‎‏‎"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‎‏‏‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‎‎‏‎‏‎‎Airplane mode‎‏‎‎‏‎"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‏‎‏‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‎‎Pattern required after device restarts‎‏‎‎‏‎"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‏‎‎‏‎‎‎‏‎Pattern required for additional security‎‏‎‎‏‎"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‏‎‎‎‏‎PIN required for additional security‎‏‎‎‏‎"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‎‎‎‏‎‏‏‎‏‏‏‏‎‎‏‏‎‎‏‏‎‏‎‎‏‎‏‏‎‎Password required for additional security‎‏‎‎‏‎"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‏‎‎‎‎‎‎‎‏‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‏‏‎‏‎‎‏‏‏‏‏‎‎Pattern required when you switch profiles‎‏‎‎‏‎"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‎‎‎‎‎‏‎‏‏‎‎‎‏‏‎‏‏‏‎‎‎‏‎‎‏‏‎‎‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎PIN required when you switch profiles‎‏‎‎‏‎"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‎‏‎‏‎‎‎‏‏‏‏‎‎‎‏‏‏‏‏‎‎‎‏‎‎‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‏‎‏‎‏‎‎‏‏‎‎‏‎Password required when you switch profiles‎‏‎‎‏‎"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‎‏‎‏‎Device locked by admin‎‏‎‎‏‎"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‏‎‎‎‎‏‏‏‏‎‎‏‎‎‎‎‎Device was locked manually‎‏‎‎‏‎"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎Device hasn\'t been unlocked for ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%d</xliff:g>‎‏‎‎‏‏‏‎ hours. Confirm pattern.‎‏‎‎‏‎</item>
-      <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‏‎‏‎Device hasn\'t been unlocked for ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%d</xliff:g>‎‏‎‎‏‏‏‎ hour. Confirm pattern.‎‏‎‎‏‎</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‎‎Device hasn\'t been unlocked for ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%d</xliff:g>‎‏‎‎‏‏‏‎ hours. Confirm PIN.‎‏‎‎‏‎</item>
-      <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‏‎‏‏‏‏‏‎‎‎‏‎‎‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‎‎‎‎‏‏‏‏‎‎Device hasn\'t been unlocked for ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%d</xliff:g>‎‏‎‎‏‏‏‎ hour. Confirm PIN.‎‏‎‎‏‎</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎Device hasn\'t been unlocked for ‎‏‎‎‏‏‎<xliff:g id="NUMBER_1">%d</xliff:g>‎‏‎‎‏‏‏‎ hours. Confirm password.‎‏‎‎‏‎</item>
-      <item quantity="one">‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‎‎‎‏‎‏‏‎‎‏‎‎‎‏‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‎‎‏‏‎‏‏‏‏‎‎‏‎‎Device hasn\'t been unlocked for ‎‏‎‎‏‏‎<xliff:g id="NUMBER_0">%d</xliff:g>‎‏‎‎‏‏‏‎ hour. Confirm password.‎‏‎‎‏‎</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‎‏‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎Not recognized‎‏‎‎‏‎"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎Not recognized‎‏‎‎‏‎"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
index 71c72a1..7be89b6 100644
--- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Bloqueo de teclado"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Ingresa el código PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Escribe el código PUK de la tarjeta SIM y el código PIN nuevo"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Código PUK de la tarjeta SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nuevo código PIN de la tarjeta SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Toca para ingresar contraseña"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Ingresa la contraseña para desbloquearlo"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Ingresa el PIN para desbloquearlo"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Ingresa tu PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Ingresa tu patrón"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Ingresa tu contraseña"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Código PIN incorrecto"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Tarjeta no válida"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Cargada"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando de manera inalámbrica"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga limitada temporalmente"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta tu cargador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Presiona Menú para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Sin tarjeta SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Contraseña del dispositivo"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Área de PIN de la tarjeta SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Área de PUK de la tarjeta SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Próxima alarma establecida: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Borrar"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Inhabilitar eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"No se puede inhabilitar la eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"No se puede inhabilitar la eSIM debido a un error."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Intro"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"¿Olvidaste el patrón?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Patrón incorrecto"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Contraseña incorrecta"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorrecto"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Vuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
       <item quantity="one">Vuelve a intentarlo en 1 segundo.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Dibuja tu patrón"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Ingresa el PIN de la tarjeta SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Ingresa el PIN de la tarjeta SIM de \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Inhabilita la tarjeta eSIM para usar el dispositivo sin servicio móvil."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Ingresa el PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Escribe la contraseña"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"La tarjeta SIM está inhabilitada. Para continuar, ingresa el código PUK. Si quieres obtener más información, comunícate con el proveedor."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"La tarjeta SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" está inhabilitada. Para continuar, ingresa el código PUK. Para obtener más información, comunícate con el proveedor."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Ingresa el código PIN deseado"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Desbloqueando tarjeta SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Escribe un PIN que tenga entre 4 y 8 números."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"El código PUK debe tener al menos 8 números."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Vuelve a ingresar el código PUK correcto. Si ingresas un código incorrecto varias veces, se inhabilitará la tarjeta SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Demasiados intentos incorrectos para el ingreso del patrón"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Escribiste tu PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. \n\nVuelve a intentarlo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Escribiste tu contraseña <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. \n\nVuelve a intentarlo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Dibujaste tu patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. \n\nVuelve a intentarlo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Se produjo un error al desbloquear la tarjeta SIM con el PIN."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Se produjo un error al desbloquear la tarjeta SIM con el PUK."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Se aceptó el código."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Sin servicio"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Cambiar método de entrada"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Modo de avión"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Se requiere el patrón después de reiniciar el dispositivo"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Se requiere el patrón por razones de seguridad"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Se requiere el PIN por razones de seguridad"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Se requiere la contraseña por razones de seguridad"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Se requiere el patrón al cambiar de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Se requiere el PIN al cambiar de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Se requiere la contraseña al cambiar de perfil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloqueado por el administrador"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"El dispositivo se bloqueó de forma manual"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Hace <xliff:g id="NUMBER_1">%d</xliff:g> horas que no se desbloquea el dispositivo. Confirma el patrón.</item>
-      <item quantity="one">Hace <xliff:g id="NUMBER_0">%d</xliff:g> hora que no se desbloquea el dispositivo. Confirma el patrón.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Hace <xliff:g id="NUMBER_1">%d</xliff:g> horas que no se desbloquea el dispositivo. Confirma el PIN.</item>
-      <item quantity="one">Hace <xliff:g id="NUMBER_0">%d</xliff:g> hora que no se desbloquea el dispositivo. Confirma el PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Hace <xliff:g id="NUMBER_1">%d</xliff:g> horas que no se desbloquea el dispositivo. Confirma la contraseña.</item>
-      <item quantity="one">Hace <xliff:g id="NUMBER_0">%d</xliff:g> hora que no se desbloquea el dispositivo. Confirma la contraseña.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"No se reconoció"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"No se reconoció"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml
index 44e613c..b0f9f33 100644
--- a/packages/SystemUI/res-keyguard/values-es/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-es/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Bloqueo"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Escribe el código PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Escribe el PUK de la tarjeta SIM y un nuevo código PIN"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Código PUK de la tarjeta SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nuevo código PIN de la tarjeta SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Toca para escribir contraseña"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Escribe la contraseña para desbloquear"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Escribe el código PIN para desbloquear"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Introduce tu PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Introduce tu patrón"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introduce tu contraseña"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"El código PIN es incorrecto."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Tarjeta no válida."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Cargado"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando sin cables"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rápidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga limitada temporalmente"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta el cargador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pulsa el menú para desbloquear la pantalla."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada para la red"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Falta la tarjeta SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Contraseña del dispositivo"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Área de PIN de la tarjeta SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Área de PUK de la tarjeta SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Próxima alarma: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Eliminar"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Inhabilita la tarjeta eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"No se puede inhabilitar la tarjeta eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"No se puede mostrar la tarjeta eSIM debido a un error."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Intro"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"¿Has olvidado el patrón?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Patrón incorrecto"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Contraseña incorrecta"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorrecto"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Vuelve a intentarlo en <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
       <item quantity="one">Vuelve a intentarlo en 1 segundo.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Dibuja tu patrón"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Introduce el PIN de la tarjeta SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Introduce el PIN de la tarjeta SIM de <xliff:g id="CARRIER">%1$s</xliff:g>."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Inhabilita la tarjeta eSIM para usar el dispositivo sin servicio móvil."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Introduce el PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Introduce tu contraseña"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"La tarjeta SIM está inhabilitada. Para continuar, introduce el código PUK. Si quieres obtener más información, ponte en contacto con el operador."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"La tarjeta SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" está inhabilitada. Para continuar, introduce el código PUK. Si quieres obtener más información, ponte en contacto con el operador."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Introduce el código PIN que quieras utilizar"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Desbloqueando la tarjeta SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Escribe un código PIN que tenga entre 4 y 8 dígitos."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"El código PUK debe tener 8 números como mínimo."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Vuelve a introducir el código PUK correcto. Si introduces un código incorrecto varias veces, se inhabilitará la tarjeta SIM de forma permanente."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Has fallado demasiadas veces al introducir el patrón"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al escribir el PIN. \n\nVuelve a intentarlo dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al introducir la contraseña. \n\nVuelve a intentarlo dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al dibujar el patrón de desbloqueo. \n\nVuelve a intentarlo dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"No se ha podido desbloquear la tarjeta SIM con el código PIN."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"No se ha podido desbloquear la tarjeta SIM con el código PUK."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"El código es válido."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Sin servicio"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Cambiar método de introducción"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Modo avión"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Debes introducir el patrón después de reiniciar el dispositivo"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Debes introducir el patrón como medida de seguridad adicional"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Debes introducir el PIN como medida de seguridad adicional"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Debes introducir la contraseña como medida de seguridad adicional"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Debes introducir el patrón cuando cambies de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Debes introducir el PIN cuando cambies de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Debes introducir la contraseña cuando cambies de perfil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloqueado por el administrador"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"El dispositivo se ha bloqueado manualmente"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">El dispositivo no se ha desbloqueado durante <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirma el patrón.</item>
-      <item quantity="one">El dispositivo no se ha desbloqueado durante <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirma el patrón.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">El dispositivo no se ha desbloqueado durante <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirma el PIN.</item>
-      <item quantity="one">El dispositivo no se ha desbloqueado durante <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirma el PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">El dispositivo no se ha desbloqueado durante <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirma la contraseña.</item>
-      <item quantity="one">El dispositivo no se ha desbloqueado durante <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirma la contraseña.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"No se reconoce"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"No se reconoce"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-et/strings.xml b/packages/SystemUI/res-keyguard/values-et/strings.xml
index e1c4c15..58b870f 100644
--- a/packages/SystemUI/res-keyguard/values-et/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-et/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Klahvilukk"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Sisestage PIN-kood"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Sisestage SIM-kaardi PUK- ja uus PIN-kood"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM-kaardi PUK-kood"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"SIM-kaardi uus PIN-kood"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Puudut. parooli sisestamiseks"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Avamiseks sisestage parool"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Avamiseks sisestage PIN-kood"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Sisestage PIN-kood"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Sisestage muster"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Sisestage parool"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Vale PIN-kood."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Kehtetu kaart."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Laetud"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Juhtmeta laadimine"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kiirlaadimine"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Aeglane laadimine"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laadimine on ajutiselt piiratud"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Ühendage laadija."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Vajutage avamiseks menüüklahvi."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Võrk on lukus"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM-kaarti pole"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Seadme parool"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM-kaardi PIN-koodi ala"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM-kaardi PUK-koodi ala"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Järgmine alarm on määratud ajaks <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Kustuta"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Keela eSIM-kaart"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM-kaarti ei saa keelata"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Vea tõttu ei saa eSIM-kaarte keelata."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Sisesta"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Unustasin mustri"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Vale muster"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Vale parool"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Vale PIN-kood"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Proovige uuesti <xliff:g id="NUMBER">%d</xliff:g> sekundi pärast.</item>
       <item quantity="one">Proovige uuesti 1 sekundi pärast.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Joonistage oma muster"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Sisestage SIM-kaardi PIN-kood."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Sisestage operaatori „<xliff:g id="CARRIER">%1$s</xliff:g>” SIM-kaardi PIN-kood."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Keelake eSIM-kaart, et seadet ilma mobiilsideteenuseta kasutada."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Sisestage PIN-kood"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Sisestage parool"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM-kaart on nüüd keelatud. Jätkamiseks sisestage PUK-kood. Lisateabe saamiseks võtke ühendust operaatoriga."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM-kaart „<xliff:g id="CARRIER">%1$s</xliff:g>” on nüüd keelatud. Jätkamiseks sisestage PUK-kood. Lisateabe saamiseks võtke ühendust operaatoriga."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Sisestage soovitud PIN-kood"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM-kaardi avamine …"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Sisestage 4–8-numbriline PIN-kood."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-koodi pikkus peab olema vähemalt kaheksa numbrit."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Sisestage uuesti õige PUK-kood. Korduvkatsete korral keelatakse SIM-kaart jäädavalt."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Liiga palju mustrikatseid"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Olete PIN-koodi <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti sisestanud. \n\nProovige <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundi pärast uuesti."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Olete parooli <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti sisestanud. \n\nProovige <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundi pärast uuesti."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Olete oma avamismustrit <xliff:g id="NUMBER_0">%1$d</xliff:g> korda valesti joonistanud. \n\nProovige <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundi pärast uuesti."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM-kaardi PIN-koodi toiming ebaõnnestus."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM-kaardi PUK-koodi toiming ebaõnnestus."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kood on õige."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Teenus puudub."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Vaheta sisestusmeetodit"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Lennukirežiim"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pärast seadme taaskäivitamist tuleb sisestada muster"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Lisaturvalisuse huvides tuleb sisestada muster"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Lisaturvalisuse huvides tuleb sisestada PIN-kood"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Lisaturvalisuse huvides tuleb sisestada parool"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Profiilide vahetamisel tuleb sisestada muster"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Profiilide vahetamisel tuleb sisestada PIN-kood"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Profiilide vahetamisel tuleb sisestada parool"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administraator lukustas seadme"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Seade lukustati käsitsi"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Seadet pole avatud <xliff:g id="NUMBER_1">%d</xliff:g> tundi. Kinnitage muster.</item>
-      <item quantity="one">Seadet pole avatud <xliff:g id="NUMBER_0">%d</xliff:g> tund. Kinnitage muster.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Seadet pole avatud <xliff:g id="NUMBER_1">%d</xliff:g> tundi. Kinnitage PIN-kood.</item>
-      <item quantity="one">Seadet pole avatud <xliff:g id="NUMBER_0">%d</xliff:g> tund. Kinnitage PIN-kood.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Seadet pole avatud <xliff:g id="NUMBER_1">%d</xliff:g> tundi. Kinnitage parool.</item>
-      <item quantity="one">Seadet pole avatud <xliff:g id="NUMBER_0">%d</xliff:g> tund. Kinnitage parool.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Ei tuvastatud"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ei tuvastatud"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-eu/strings.xml b/packages/SystemUI/res-keyguard/values-eu/strings.xml
index 8550164..2366156 100644
--- a/packages/SystemUI/res-keyguard/values-eu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-eu/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Teklatu-babeslea"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Idatzi PIN kodea"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Idatzi SIMaren PUKa eta PIN kode berria"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM txartelaren PUK kodea"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"SIMaren PIN kode berria"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Pasahitza idazteko, sakatu hau"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Idatzi desblokeatzeko pasahitza"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Idatzi desblokeatzeko PINa"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Idatzi PINa"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Marraztu eredua"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Idatzi pasahitza"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN kodea okerra da."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Txartelak ez du balio."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Kargatuta"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hari gabe kargatzen"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Bizkor kargatzen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mantso kargatzen"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kargatzeko aukera mugatuta dago aldi baterako"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Konektatu kargagailua."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Desblokeatzeko, sakatu Menua."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sarea blokeatuta dago"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Ez dago SIM txartelik"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Gailuaren pasahitza"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM txartelaren PIN kodearen eremua"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM txartelaren PUK kodearen eremua"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Hurrengo alarmak ordu honetan joko du: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Ezabatu"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Desgaitu eSIM txartela"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Ezin da desgaitu eSIM txartela"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Errore bat gertatu da eta ezin da desgaitu eSIM txartela."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Sartu"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Eredua ahaztu zaizu"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Eredua ez da zuzena"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Pasahitza ez da zuzena"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN hori ez da zuzena"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Saiatu berriro <xliff:g id="NUMBER">%d</xliff:g> segundo igarotakoan.</item>
       <item quantity="one">Saiatu berriro segundo bat igarotakoan.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Marraztu eredua"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Idatzi SIMaren PINa."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Idatzi \"<xliff:g id="CARRIER">%1$s</xliff:g>\" operadorearen SIM txartelaren PINa."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desgaitu eSIM txartela gailua zerbitzu mugikorrik gabe erabiltzeko."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Idatzi PINa"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Idatzi pasahitza"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Desgaitu egin da SIM txartela. Aurrera egiteko, idatzi PUK kodea. Xehetasunak lortzeko, jarri operadorearekin harremanetan."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Desgaitu egin da \"<xliff:g id="CARRIER">%1$s</xliff:g>\" operadorearen SIM txartela. Aurrera egiteko, idatzi PUK kodea. Xehetasunak jakiteko, jarri operadorearekin harremanetan."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Idatzi erabili nahi duzun PIN kodea"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM txartela desblokeatzen…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Idatzi 4 eta 8 zenbaki bitarteko PIN bat."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kodeak 8 zenbaki izan behar ditu gutxienez."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Idatzi berriro PUK kode zuzena. Hainbat saiakera oker eginez gero, betiko desgaituko da SIM txartela."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Eredua marrazteko saiakera gehiegi egin dira"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz idatzi duzu PINa, baina huts egin duzu denetan. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz idatzi duzu pasahitza, baina huts egin duzu denetan. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"<xliff:g id="NUMBER_0">%1$d</xliff:g> aldiz marraztu duzu desblokeatzeko eredua, baina huts egin duzu denetan. \n\nSaiatu berriro <xliff:g id="NUMBER_1">%2$d</xliff:g> segundo barru."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Huts egin du SIM txartelaren PIN kodearen eragiketak!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Huts egin du SIM txartelaren PUK kodearen eragiketak!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Onartu da kodea!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Ez dago konektatuta inongo saretara."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Aldatu idazketa-metodoa"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Hegaldi modua"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Eredua marraztu beharko duzu gailua berrabiarazten denean"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Eredua behar da gailua babestuago izateko"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PINa behar da gailua babestuago izateko"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Pasahitza behar da gailua babestuago izateko"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Eredua marraztu beharko duzu profilez aldatzen baduzu"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PINa idatzi beharko duzu profilez aldatzen baduzu"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Pasahitza idatzi beharko duzu profilez aldatzen baduzu"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administratzaileak blokeatu egin du gailua"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Eskuz blokeatu da gailua"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Gailua ez da desblokeatu <xliff:g id="NUMBER_1">%d</xliff:g> orduz. Berretsi eredua.</item>
-      <item quantity="one">Gailua ez da desblokeatu <xliff:g id="NUMBER_0">%d</xliff:g> orduz. Berretsi eredua.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Gailua ez da desblokeatu <xliff:g id="NUMBER_1">%d</xliff:g> orduz. Berretsi PINa.</item>
-      <item quantity="one">Gailua ez da desblokeatu <xliff:g id="NUMBER_0">%d</xliff:g> orduz. Berretsi PINa.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Gailua ez da desblokeatu <xliff:g id="NUMBER_1">%d</xliff:g> orduz. Berretsi pasahitza.</item>
-      <item quantity="one">Gailua ez da desblokeatu <xliff:g id="NUMBER_0">%d</xliff:g> orduz. Berretsi pasahitza.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Ez da ezagutu"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ez da ezagutu"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-fa/strings.xml b/packages/SystemUI/res-keyguard/values-fa/strings.xml
index 0a036c8..e110d08 100644
--- a/packages/SystemUI/res-keyguard/values-fa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fa/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"کد پین را وارد کنید"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"‏PUK سیم‌کارت و کد پین جدید را تایپ کنید"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"‏کد PUK سیم‌کارت"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"کد پین سیم جدید"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"برای تایپ گذرواژه لمس کنید"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"برای بازکردن قفل، گذرواژه را وارد کنید"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"برای بازکردن قفل، پین را تایپ کنید"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"پین را وارد کنید"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"الگویتان را وارد کنید"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"گذرواژه‌تان را وارد کنید"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"کد پین اشتباه است."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"کارت نامعتبر"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"شارژ کامل شد"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ بی‌سیم"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • درحال شارژ سریع"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آهسته‌آهسته شارژ می‌شود"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • شارژ موقتاً محدود شده است"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"شارژر را وصل کنید."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"برای باز کردن قفل روی «منو» فشار دهید."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"شبکه قفل شد"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"سیم‌کارت موجود نیست"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"گذرواژه دستگاه"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"قسمت پین سیم‌کارت"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"‏قسمت PUK سیم‌کارت"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"زنگ بعدی برای <xliff:g id="ALARM">%1$s</xliff:g> تنظیم شد"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"حذف"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"‏غیرفعال کردن eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"سیم‌کارت داخلی غیرفعال نشد"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"به دلیل بروز خطا، سیم‌کارت داخلی غیرفعال نشد."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"الگو را فراموش کرده‌اید"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"الگو اشتباه است"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"گذرواژه اشتباه است"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"پین اشتباه"</string>
@@ -68,12 +56,9 @@
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> ثانیه دیگر دوباره امتحان کنید.</item>
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> ثانیه دیگر دوباره امتحان کنید.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"الگوی خود را رسم کنید"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"پین سیم‌کارت را وارد کنید."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"پین سیم‌کارت «<xliff:g id="CARRIER">%1$s</xliff:g>» را وارد کنید."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g>برای استفاده از دستگاه بدون سرویس همراه، سیم‌کارت داخلی را غیرفعال کنید."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"کد پین را وارد کنید"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"گذرواژه را وارد کنید"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"اکنون سیم‌کارت غیرفعال است. کد پین را برای ادامه وارد کنید. برای جزئیات با شرکت مخابراتی خود تماس بگیرید."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"‏اکنون سیم‌کارت «<xliff:g id="CARRIER">%1$s</xliff:g>» غیرفعال شده است. برای ادامه دادن، کد PUK را وارد کنید. برای اطلاع از جزئیات با شرکت مخابراتی تماس بگیرید."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"کد پین دلخواه را وارد کنید"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"درحال باز کردن قفل سیم‌کارت..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"یک پین ۴ تا ۸ رقمی را تایپ کنید."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"کد پین باید ۸ عدد یا بیشتر باشد."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"کد پین صحیح را دوباره وارد کنید. تلاش‌های مکرر به‌طور دائم سیم‌کارت را غیرفعال خواهد کرد."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"‏تلاش‎های زیادی برای کشیدن الگو صورت گرفته است"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"پین خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه تایپ کردید. \n\nپس از <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"گذرواژه خود را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه تایپ کردید. \n\nپس از <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"الگوی بازگشایی قفل را <xliff:g id="NUMBER_0">%1$d</xliff:g> بار اشتباه کشیده‌اید. \n\nلطفاً پس‌از <xliff:g id="NUMBER_1">%2$d</xliff:g> ثانیه دوباره امتحان کنید."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"عملیات پین سیم‌کارت ناموفق بود!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"‏عملیات PUK سیم‌کارت ناموفق بود!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"کد پذیرفته شد!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"سرویسی وجود ندارد."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"تغییر روش ورودی"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"حالت هواپیما"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"بعد از بازنشانی دستگاه باید الگو وارد شود"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"برای ایمنی بیشتر باید الگو وارد شود"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"برای ایمنی بیشتر باید پین وارد شود"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"برای ایمنی بیشتر باید گذرواژه وارد شود"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"بعد از تغییر نمایه‌ها باید الگو وارد شود"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"بعد از تغییر نمایه‌ها باید پین وارد شود"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"بعد از تغییر نمایه‌ها باید گذرواژه وارد شود"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"دستگاه توسط سرپرست سیستم قفل شده است"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"دستگاه به‌صورت دستی قفل شده است"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">قفل دستگاه <xliff:g id="NUMBER_1">%d</xliff:g> ساعت باز نشده است. الگو را تأیید کنید.</item>
-      <item quantity="other">قفل دستگاه <xliff:g id="NUMBER_1">%d</xliff:g> ساعت باز نشده است. الگو را تأیید کنید.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">قفل دستگاه <xliff:g id="NUMBER_1">%d</xliff:g> ساعت باز نشده است. پین را تأیید کنید.</item>
-      <item quantity="other">قفل دستگاه <xliff:g id="NUMBER_1">%d</xliff:g> ساعت باز نشده است. پین را تأیید کنید.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">قفل دستگاه <xliff:g id="NUMBER_1">%d</xliff:g> ساعت باز نشده است. گذرواژه را تأیید کنید.</item>
-      <item quantity="other">قفل دستگاه <xliff:g id="NUMBER_1">%d</xliff:g> ساعت باز نشده است. گذرواژه را تأیید کنید.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"شناسایی نشد"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"شناسایی نشد"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-fi/strings.xml b/packages/SystemUI/res-keyguard/values-fi/strings.xml
index 5432358..82927e1 100644
--- a/packages/SystemUI/res-keyguard/values-fi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fi/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Näppäinvahti"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Anna PIN-koodi."</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Anna SIM-kortin PUK-koodi ja uusi PIN-koodi."</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM-kortin PUK-koodi"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Uusi SIM-kortin PIN-koodi"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Kosketa ja anna salasana"</font>"."</string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Poista lukitus antamalla salasana."</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Poista lukitus antamalla PIN-koodi."</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Syötä PIN-koodi"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Piirrä kuvio"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Kirjoita salasana"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Väärä PIN-koodi"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Virheellinen kortti"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Ladattu"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan langattomasti"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan nopeasti"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ladataan hitaasti"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lataamista rajoitettu väliaikaisesti"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Kytke laturi."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Poista lukitus painamalla Valikkoa."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Verkko lukittu"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Ei SIM-korttia"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Laitteen salasana"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM-kortin PIN-koodin alue"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM-kortin PUK-koodin alue"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Seuraava hälytys asetettu: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Poista"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Poista eSIM käytöstä"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIMiä ei voi poistaa käytöstä"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Tapahtui virhe, eikä eSIMiä voitu poistaa käytöstä."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Unohtunut kuvio"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Väärä kuvio"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Väärä salasana"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Väärä PIN-koodi"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Yritä uudelleen <xliff:g id="NUMBER">%d</xliff:g> sekunnin kuluttua.</item>
       <item quantity="one">Yritä uudelleen 1 sekunnin kuluttua.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Piirrä kuvio"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Anna SIM-kortin PIN-koodi."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Anna operaattorin <xliff:g id="CARRIER">%1$s</xliff:g> SIM-kortin PIN-koodi."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Poista eSIM käytöstä, jos haluat käyttää laitetta ilman mobiililiittymää."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Anna PIN-koodi."</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Lisää salasana"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM-kortti on nyt poistettu käytöstä. Jatka antamalla PUK-koodi. Saat lisätietoja ottamalla yhteyttä operaattoriin."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Operaattorin <xliff:g id="CARRIER">%1$s</xliff:g> SIM-kortti on nyt lukittu. Jatka antamalla PUK-koodi. Saat lisätietoja operaattoriltasi."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Anna haluamasi PIN-koodi."</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM-kortin lukitusta avataan…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Anna 4–8-numeroinen PIN-koodi."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-koodissa tulee olla vähintään 8 numeroa."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Anna uudelleen oikea PUK-koodi. Jos teet liian monta yritystä, SIM-kortti poistetaan käytöstä pysyvästi."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Liikaa kuvionpiirtoyrityksiä"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Olet kirjoittanut PIN-koodin väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. \n\nYritä uudelleen <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunnin kuluttua."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Olet kirjoittanut salasanan väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. \n\nYritä uudelleen <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunnin kuluttua."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Olet piirtänyt lukituksenpoistokuvion väärin <xliff:g id="NUMBER_0">%1$d</xliff:g> kertaa. \n\nYritä uudelleen <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunnin kuluttua."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM-kortin PIN-toiminto epäonnistui."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM-kortin PUK-toiminto epäonnistui."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Koodi hyväksytty"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Ei yhteyttä"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Vaihda syöttötapaa."</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Lentokonetila"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Kuvio vaaditaan laitteen uudelleenkäynnistyksen jälkeen."</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Kuvio vaaditaan suojauksen parantamiseksi."</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN-koodi vaaditaan suojauksen parantamiseksi."</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Salasana vaaditaan suojauksen parantamiseksi."</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Kuvio vaaditaan profiilia vaihdettaessa."</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PIN-koodi vaaditaan profiilia vaihdettaessa."</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Salasana vaaditaan profiilia vaihdettaessa."</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Järjestelmänvalvoja lukitsi laitteen."</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Laite lukittiin manuaalisesti"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Laitteen lukitusta ei ole avattu <xliff:g id="NUMBER_1">%d</xliff:g> tuntiin. Vahvista kuvio.</item>
-      <item quantity="one">Laitteen lukitusta ei ole avattu <xliff:g id="NUMBER_0">%d</xliff:g> tuntiin. Vahvista kuvio.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Laitteen lukitusta ei ole avattu <xliff:g id="NUMBER_1">%d</xliff:g> tuntiin. Vahvista PIN-koodi.</item>
-      <item quantity="one">Laitteen lukitusta ei ole avattu <xliff:g id="NUMBER_0">%d</xliff:g> tuntiin. Vahvista PIN-koodi.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Laitteen lukitusta ei ole avattu <xliff:g id="NUMBER_1">%d</xliff:g> tuntiin. Vahvista salasana.</item>
-      <item quantity="one">Laitteen lukitusta ei ole avattu <xliff:g id="NUMBER_0">%d</xliff:g> tuntiin. Vahvista salasana.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Ei tunnistettu"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ei tunnistettu"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
index f8c8cad..3646394 100644
--- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Verrouillage du clavier"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Entrez le NIP."</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Entrez le code PUK et le nouveau NIP de la carte SIM"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Code PUK de la carte SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nouveau NIP de la carte SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Touchez ici pour entrer le mot de passe"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Entrez le mot de passe pour déverrouiller le clavier."</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Entrez le NIP pour déverrouiller le clavier."</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Entrez votre NIP"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Entrez votre schéma"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Entrez votre mot de passe"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"NIP erroné."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cette carte n\'est pas valide."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Chargé"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • En recharge sans fil"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"En recharge rapide : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"En recharge lente : <xliff:g id="PERCENTAGE">%s</xliff:g>"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge temporairement limitée"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Branchez votre chargeur."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur la touche Menu pour déverrouiller l\'appareil."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Aucune carte SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Mot de passe de l\'appareil"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Zone du NIP de la carte SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Zone du code PUK de la carte SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Heure de la prochaine alarme : <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Supprimer"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Désactiver la carte eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Impossible de désactiver la carte eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"La carte eSIM ne peut pas être réinitialisée à cause d\'une erreur."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Entrée"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"J\'ai oublié le schéma"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Schéma incorrect"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Mot de passe incorrect"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"NIP incorrect"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">Réessayer dans <xliff:g id="NUMBER">%d</xliff:g> seconde.</item>
       <item quantity="other">Réessayer dans <xliff:g id="NUMBER">%d</xliff:g> secondes.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Dessinez votre schéma"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Entrez le NIP de la carte SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Entrez le NIP de la carte SIM pour « <xliff:g id="CARRIER">%1$s</xliff:g> »."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Désactivez la carte eSIM pour utiliser l\'appareil sans service cellulaire."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Entrez le NIP"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Entrez votre mot de passe."</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Pour obtenir plus de détails, communiquez avec votre fournisseur de services."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Le carte SIM « <xliff:g id="CARRIER">%1$s</xliff:g> » est maintenant désactivée. Entrez le code PUK pour continuer. Pour obtenir plus de détails, communiquez avec votre fournisseur de services."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Entrez le NIP que vous souhaitez utiliser"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Déblocage de la carte SIM en cours…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Veuillez entrer un NIP comprenant entre quatre et huit chiffres."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Le code PUK doit contenir au moins 8 chiffres."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Veuillez entrer de nouveau le code PUK correct. Trop de tentatives répétées désactiveront définitivement la carte SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Trop de tentatives."</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Vous avez entré un NIP incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises. \n\nVeuillez réessayer dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Vous avez entré un mot de passe incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Le déverrouillage par NIP de la carte SIM a échoué."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Le déverrouillage de la carte SIM par code PUK a échoué."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Code accepté"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Aucun service"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Changer de méthode d\'entrée"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Mode Avion"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Le schéma est exigé après le redémarrage de l\'appareil"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Le schéma est exigé pour plus de sécurité"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Le NIP est exigé pour plus de sécurité"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Le mot de passe est exigé pour plus de sécurité"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Le schéma est exigé lorsque vous changez de profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Le NIP est exigé lorsque vous changez de profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Le mot de passe est exigé lorsque vous changez de profil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"L\'appareil a été verrouillé par l\'administrateur"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"L\'appareil a été verrouillé manuellement"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le schéma.</item>
-      <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le schéma.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le NIP.</item>
-      <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le NIP.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le mot de passe.</item>
-      <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le mot de passe.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Doigt non reconnu"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Doigt non reconnu"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml
index 1e4b33c..6e1ee96 100644
--- a/packages/SystemUI/res-keyguard/values-fr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Protection des touches"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Saisissez le code PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Saisissez la clé PUK et le nouveau code PIN de la carte SIM"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Clé PUK de la carte SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nouveau code PIN de la carte SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Appuyez pour saisir mot passe"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Saisissez le mot de passe pour déverrouiller le clavier"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Saisissez le code pour déverrouiller le clavier"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Saisissez le code d\'accès"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Tracez le schéma"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Saisissez votre mot de passe"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Le code est incorrect."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Carte non valide."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Chargé"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • En charge sans fil"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge rapide…"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge lente…"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Recharge momentanément limitée"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Branchez votre chargeur."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Appuyez sur \"Menu\" pour déverrouiller le clavier."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Réseau verrouillé"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Pas de carte SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Mot de passe de l\'appareil"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Champ du code PIN de la carte SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Champ de la clé PUK de la carte SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Date et heure de la prochaine alarme : <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Supprimer"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Désactiver la carte eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Impossible de désactiver la carte eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Impossible de désactiver la carte eSIM en raison d\'une erreur."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Entrée"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"J\'ai oublié le schéma"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Schéma incorrect"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Mot de passe incorrect"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Code incorrect"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> seconde.</item>
       <item quantity="other">Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Dessinez votre schéma"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Saisissez le code PIN de la carte SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Saisissez le code PIN de la carte SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Désactivez la carte eSIM pour utiliser l\'appareil sans service mobile."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Saisissez le code"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Saisissez le mot de passe"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"La carte SIM est maintenant désactivée. Pour continuer, saisissez la clé PUK. Contactez votre opérateur pour en savoir plus."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"La carte SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" est maintenant désactivée. Pour continuer, saisissez la clé PUK. Contactez votre opérateur pour en savoir plus."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Saisissez le code PIN de votre choix"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Déblocage de la carte SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Saisissez un code PIN comprenant 4 à 8 chiffres."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"La clé PUK doit contenir au moins 8 chiffres."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Veuillez saisir de nouveau la clé PUK. Après plusieurs tentatives, la carte SIM sera définitivement désactivée."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Trop de tentatives"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Vous avez saisi un code incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nRéessayez dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Vous avez saisi un mot de passe incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nRéessayez dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nRéessayez dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Échec du déverrouillage à l\'aide du code PIN de la carte SIM."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Échec du déverrouillage à l\'aide de la clé PUK de la carte SIM."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Code accepté."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Aucun service."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Changer le mode de saisie"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Mode Avion"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Veuillez dessiner le schéma après le redémarrage de l\'appareil"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Veuillez dessiner le schéma pour renforcer la sécurité"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Veuillez saisir le code pour renforcer la sécurité"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Veuillez saisir le mot de passe pour renforcer la sécurité"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Veuillez dessiner le schéma lorsque vous changez de profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Veuillez saisir le code lorsque vous changez de profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Veuillez saisir le mot de passe lorsque vous changez de profil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Appareil verrouillé par l\'administrateur"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Appareil verrouillé manuellement"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le schéma.</item>
-      <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le schéma.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le code.</item>
-      <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le code.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heure. Confirmez le mot de passe.</item>
-      <item quantity="other">L\'appareil n\'a pas été déverrouillé depuis <xliff:g id="NUMBER_1">%d</xliff:g> heures. Confirmez le mot de passe.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Non reconnu"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Non reconnu"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-gl/strings.xml b/packages/SystemUI/res-keyguard/values-gl/strings.xml
index 60a2ea4..123b8c1 100644
--- a/packages/SystemUI/res-keyguard/values-gl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gl/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Bloqueo de teclado"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Escribe o código PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Escribe o PUK da SIM e o código PIN novo"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Código PUK da SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Código PIN da SIM novo"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Toca e escribe o contrasinal"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Escribe o contrasinal para desbloquear"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Escribe o PIN para desbloquear"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Introduce o teu PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Introduce o padrón"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introduce o contrasinal"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Código PIN incorrecto"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"A tarxeta non é válida."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Cargado"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando sen fíos"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Cargando lentamente"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carga limitada temporalmente"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecta o cargador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Preme Menú para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Bloqueada pola rede"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Sen tarxeta SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Contrasinal do dispositivo"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Área do PIN da tarxeta SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Área do PUK da tarxeta SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Próxima alarma definida para: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Eliminar"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Desactivar eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Non se puido desactivar a eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"A eSIM non se puido desactivar debido a un erro."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Intro"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Esqueciches o padrón"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"O padrón é incorrecto"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"O contrasinal é incorrecto"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorrecto"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Téntao de novo dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
       <item quantity="one">Téntao de novo dentro de 1 segundo.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Debuxa o teu padrón"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Introduce o PIN da SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Introduce o PIN da SIM para \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desactiva a eSIM para usar o dispositivo sen o servizo móbil."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Introduce o PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Escribe o teu contrasinal"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Agora a tarxeta SIM está desactivada. Introduce o código PUK para continuar. Ponte en contacto co operador para obter máis información."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Agora a SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" está desactivada. Introduce o código PUK para continuar. Ponte en contacto co operador para obter máis información."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Introduce o código PIN desexado"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Desbloqueando tarxeta SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Escribe un PIN que teña entre 4 e 8 números."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"O código PUK debe ter 8 números como mínimo."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Volve introducir o código PUK correcto. Se realizas intentos repetidos é posible que se desactive a tarxeta SIM permanentemente."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Tentaches debuxar o padrón moitas veces"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Introduciches o PIN incorrectamente <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. \n\nTéntao de novo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Introduciches o contrasinal incorrectamente <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. \n\nTéntao de novo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Debuxaches incorrectamente o padrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces. \n\nTéntao de novo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Produciuse un erro no funcionamento do PIN da SIM"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Produciuse un erro ao tentar desbloquear a tarxeta SIM co código PUK."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Código válido"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Non hai servizo."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Cambia o método de introdución"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Modo avión"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"É necesario o padrón despois do reinicio do dispositivo"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"É necesario o padrón para obter seguranza adicional"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"É necesario o PIN para obter seguranza adicional"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"É necesario o contrasinal para obter seguranza adicional"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"É necesario o padrón para cambiar os perfís"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"É necesario o PIN para cambiar os perfís"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"É necesario o contrasinal para cambiar os perfís"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"O administrador bloqueou o dispositivo"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"O dispositivo bloqueouse manualmente"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">O dispositivo non se desbloqueou durante <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirma o padrón.</item>
-      <item quantity="one">O dispositivo non se desbloqueou durante <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirma o padrón.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">O dispositivo non se desbloqueou durante <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirma o PIN.</item>
-      <item quantity="one">O dispositivo non se desbloqueou durante <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirma o PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">O dispositivo non se desbloqueou durante <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirma o contrasinal.</item>
-      <item quantity="one">O dispositivo non se desbloqueou durante <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirma o contrasinal.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Non se recoñeceu"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Non se recoñeceu"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-gu/strings.xml b/packages/SystemUI/res-keyguard/values-gu/strings.xml
index e87ee92..1ca39d7 100644
--- a/packages/SystemUI/res-keyguard/values-gu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-gu/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"કીગાર્ડ"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"પિન કોડ લખો"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"સિમ PUK અને નવો પિન કોડ લખો"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"સિમ PUK કોડ"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"નવો સિમ પિન કોડ"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"પાસવર્ડ લખવા માટે સ્પર્શ કરો"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"અનલૉક કરવા માટે પાસવર્ડ લખો"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"અનલૉક કરવા માટે પિન લખો"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"તમારો પિન દાખલ કરો"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"તમારી પૅટર્ન દાખલ કરો"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"તમારો પાસવર્ડ દાખલ કરો"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"ખોટો પિન કોડ."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"અમાન્ય કાર્ડ."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"ચાર્જ થઈ ગયું"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • વાયરલેસથી ચાર્જિંગ"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ઝડપથી ચાર્જિંગ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ધીમેથી ચાર્જિંગ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ચાર્જ કરવાનું થોડા સમય માટે મર્યાદિત કરવામાં આવ્યું છે"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"તમારું ચાર્જર કનેક્ટ કરો."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"અનલૉક કરવા માટે મેનૂ દબાવો."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"નેટવર્ક લૉક થયું"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"કોઈ સિમ કાર્ડ નથી"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"ઉપકરણનો પાસવર્ડ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"સિમ પિન ક્ષેત્ર"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"સિમ PUK ક્ષેત્ર"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"<xliff:g id="ALARM">%1$s</xliff:g> માટે આગલું એલાર્મ સેટ કર્યું"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"ડિલીટ કરો"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIMને અક્ષમ કરો"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"ઇ-સિમ બંધ કરી શકાતું નથી"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"એક ભૂલને લીધે ઇ-સિમ બંધ કરી શકાતું નથી."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"દાખલ કરો"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"પૅટર્ન ભૂલી ગયાં"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"ખોટી પૅટર્ન"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"ખોટો પાસવર્ડ"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"ખોટો પિન"</string>
@@ -68,12 +56,9 @@
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> સેકન્ડમાં ફરી પ્રયાસ કરો.</item>
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> સેકન્ડમાં ફરી પ્રયાસ કરો.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"તમારી પૅટર્ન દોરો"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"સિમ પિન દાખલ કરો"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" માટે સિમ પિન દાખલ કરો."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> મોબાઇલ સેવા વગર ઉપકરણનો ઉપયોગ કરવા માટે ઇ-સિમને બંધ કરો."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"પિન દાખલ કરો"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"પાસવર્ડ દાખલ કરો"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"સિમ હમણાં અક્ષમ કરેલ છે. ચાલુ રાખવા માટે PUK કોડ દાખલ કરો. વિગતો માટે કૅરિઅરનો સંપર્ક કરો."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"સિમ \"<xliff:g id="CARRIER">%1$s</xliff:g>\" હમણાં અક્ષમ કરેલ છે. ચાલુ રાખવા માટે PUK કોડ દાખલ કરો. વિગતો માટે કૅરિઅરનો સંપર્ક કરો."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"જોઈતો પિન કોડ દાખલ કરો"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"સિમ કાર્ડ અનલૉક કરી રહ્યાં છીએ…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 થી 8 સંખ્યાનો હોય તેવો એક પિન લખો."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK કોડ 8 કે તેનાથી વધુ સંખ્યાનો હોવો જોઈએ."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"સાચો PUK કોડ ફરીથી દાખલ કરો. પુનરાવર્તિત પ્રયાસો સિમ ને કાયમી રીતે અક્ષમ કરશે."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"ઘણા બધા પૅટર્ન પ્રયાસો"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"તમારો પિન તમે <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે લખ્યો છે. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"તમારો પાસવર્ડ તમે <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે લખ્યો છે. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> સેકંડમાં ફરીથી પ્રયાસ કરો."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"તમારી અનલૉક પૅટર્ન તમે <xliff:g id="NUMBER_0">%1$d</xliff:g> વખત ખોટી રીતે દોરી છે. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> સેકન્ડમાં ફરીથી પ્રયાસ કરો."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"સિમ પિન ઑપરેશન નિષ્ફળ થયું!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"સિમ PUK ઓપરેશન નિષ્ફળ થયું!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"કોડ સ્વીકાર્યો!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"કોઈ સેવા નથી."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ઇનપુટ પદ્ધતિ સ્વિચ કરો"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"એરપ્લેન મોડ"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ઉપકરણનો પુનઃપ્રારંભ થાય તે પછી પૅટર્ન જરૂરી છે"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"વધારાની સુરક્ષા માટે પૅટર્ન જરૂરી છે"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"વધારાની સુરક્ષા માટે પિન જરૂરી છે"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"વધારાની સુરક્ષા માટે પાસવર્ડ જરૂરી છે"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"જ્યારે તમે પ્રોફાઇલો સ્વિચ કરો ત્યારે પૅટર્ન જરૂરી છે"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"જ્યારે તમે પ્રોફાઇલો સ્વિચ કરો ત્યારે પિન જરૂરી છે"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"જ્યારે તમે પ્રોફાઇલો સ્વિચ કરો ત્યારે પાસવર્ડ જરૂરી છે"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"વ્યવસ્થાપકે ઉપકરણ લૉક કરેલું છે"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ઉપકરણ મેન્યુઅલી લૉક કર્યું હતું"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">ઉપકરણને <xliff:g id="NUMBER_1">%d</xliff:g> કલાક માટે અનલૉક કરવામાં આવ્યું નથી. પેટર્નની પુષ્ટિ કરો.</item>
-      <item quantity="other">ઉપકરણને <xliff:g id="NUMBER_1">%d</xliff:g> કલાક માટે અનલૉક કરવામાં આવ્યું નથી. પેટર્નની પુષ્ટિ કરો.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">ઉપકરણને <xliff:g id="NUMBER_1">%d</xliff:g> કલાક માટે અનલૉક કરવામાં આવ્યું નથી. પિનની પુષ્ટિ કરો.</item>
-      <item quantity="other">ઉપકરણને <xliff:g id="NUMBER_1">%d</xliff:g> કલાક માટે અનલૉક કરવામાં આવ્યું નથી. પિનની પુષ્ટિ કરો.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">ઉપકરણને <xliff:g id="NUMBER_1">%d</xliff:g> કલાક માટે અનલૉક કરવામાં આવ્યું નથી. પાસવર્ડની પુષ્ટિ કરો.</item>
-      <item quantity="other">ઉપકરણને <xliff:g id="NUMBER_1">%d</xliff:g> કલાક માટે અનલૉક કરવામાં આવ્યું નથી. પાસવર્ડની પુષ્ટિ કરો.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"ઓળખાયેલ નથી"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"ઓળખાયેલ નથી"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-hi/strings.xml b/packages/SystemUI/res-keyguard/values-hi/strings.xml
index e53964d..e017a6b 100644
--- a/packages/SystemUI/res-keyguard/values-hi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hi/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"कीगार्ड"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"पिन कोड लिखें"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM PUK और नया पिन कोड लिखें"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK कोड"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"नया SIM पिन कोड"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"पासवर्ड लिखने के लिए छुएं"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"अनलॉक करने के लिए पासवर्ड लिखें"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"अनलॉक करने के लिए पिन लिखें"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"अपना पिन डालें"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"अपना पैटर्न डालें"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"अपना पासवर्ड डालें"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"गलत पिन कोड."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"गलत कार्ड."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"चार्ज हो गई है"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वायरलेस तरीके से चार्ज हो रहा है"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तेज़ चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • धीरे चार्ज हो रहा है"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • कुछ समय के लिए चार्जिंग रोक दी गई"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"अपना चार्जर कनेक्‍ट करें."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"लॉक खोलने के लिए मेन्यू दबाएं."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक किया हुआ है"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"कोई सिम कार्ड नहीं है"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"डिवाइस का पासवर्ड"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM पिन क्षेत्र"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK क्षेत्र"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"अगला अलार्म <xliff:g id="ALARM">%1$s</xliff:g> बजे के लिए सेट किया गया है"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"मिटाएं"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM अक्षम करें"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"ई-सिम बंद नहीं किया जा सकता"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"किसी गड़बड़ी की वजह से ई-सिम बंद नहीं किया जा सकता."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"पैटर्न भूल गए हैं"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"डाला गया पैटर्न गलत है"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"डाला गया पासवर्ड गलत है"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"गलत पिन"</string>
@@ -68,12 +56,9 @@
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> सेकंड में फिर से कोशिश करें.</item>
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> सेकंड में फिर से कोशिश करें.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"अपना पैटर्न बनाएं"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"सिम पिन डालें."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" के लिए सिम पिन डालें"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> मोबाइल सेवा के बिना डिवाइस का इस्तेमाल करने के लिए ई-सिम बंद करें."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"पिन डालें"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"पासवर्ड डालें"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"सिम अब काम नहीं करेगा. जारी रखने के लिए PUK कोड डालें. ज़्यादा जानकारी के लिए अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करें."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" का सिम अब काम नहीं करेगा. जारी रखने के लिए PUK कोड डालें. ज़्यादा जानकारी के लिए अपनी मोबाइल और इंटरनेट सेवा देने वाली कंपनी से संपर्क करें."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"मनचाहा पिन कोड डालें"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM कार्ड अनलॉक हो रहा है…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"कोई ऐसा पिन लिखें, जिसमें 4 से 8 अंक हों."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK कोड 8 या ज़्यादा संख्या वाला होना चाहिए."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"सही PUK कोड दोबारा डालें. बार-बार कोशिश करने से SIM हमेशा के लिए अक्षम हो जाएगा."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"पैटर्न के लिए बहुत ज़्यादा बार कोशिश की गई है"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"आप अपना पिन <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"आप अपना पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"आपने अपने लॉक खोलने के पैटर्न को <xliff:g id="NUMBER_0">%1$d</xliff:g> बार गलत तरीके से ड्रॉ किया है. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंड में फिर से कोशिश करें."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM पिन की कार्यवाही विफल रही!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK की कार्यवाही विफल रही!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"कोड स्वीकार किया गया!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"कोई सेवा नहीं."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"इनपुट का तरीका बदलें"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"हवाई जहाज़ मोड"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"डिवाइस फिर से चालू होने के बाद पैटर्न ज़रूरी है"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"अतिरिक्त सुरक्षा के लिए पैटर्न ज़रूरी है"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"अतिरिक्त सुरक्षा के लिए पिन ज़रूरी है"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"अतिरिक्त सुरक्षा के लिए पासवर्ड ज़रूरी है"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"प्रोफ़ाइल स्विच करते समय पैटर्न ज़रूरी है"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"प्रोफ़ाइल स्विच करते समय पिन ज़रूरी है"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"प्रोफ़ाइल स्विच करते समय पासवर्ड ज़रूरी है"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"व्यवस्थापक ने डिवाइस को लॉक किया है"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"डिवाइस को मैन्युअल रूप से लॉक किया गया था"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">डिवाइस को <xliff:g id="NUMBER_1">%d</xliff:g> घंटों से अनलॉक नहीं किया गया है. पैटर्न की पुष्टि करें.</item>
-      <item quantity="other">डिवाइस को <xliff:g id="NUMBER_1">%d</xliff:g> घंटों से अनलॉक नहीं किया गया है. पैटर्न की पुष्टि करें.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">डिवाइस को <xliff:g id="NUMBER_1">%d</xliff:g> घंटों से अनलॉक नहीं किया गया है. पिन की पुष्‍टि करें.</item>
-      <item quantity="other">डिवाइस को <xliff:g id="NUMBER_1">%d</xliff:g> घंटों से अनलॉक नहीं किया गया है. पिन की पुष्‍टि करें.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">डिवाइस को <xliff:g id="NUMBER_1">%d</xliff:g> घंटों से अनलॉक नहीं किया गया है. पासवर्ड की पुष्टि करें.</item>
-      <item quantity="other">डिवाइस को <xliff:g id="NUMBER_1">%d</xliff:g> घंटों से अनलॉक नहीं किया गया है. पासवर्ड की पुष्टि करें.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"पहचान नहीं हो पाई"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"पहचान नहीं हो पाई"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-hr/strings.xml b/packages/SystemUI/res-keyguard/values-hr/strings.xml
index 3f49d96..123f423 100644
--- a/packages/SystemUI/res-keyguard/values-hr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hr/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Zaštita tipkovnice"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Unesite PIN kôd"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Unesite PUK i novi PIN kôd SIM kartice"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK kôd SIM kartice"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Novi PIN za SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Dodirnite za unos zaporke"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Unesite zaporku da biste otključali"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Unesite PIN da biste otključali"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Unesite PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Unesite uzorak"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Unesite zaporku"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN kôd nije točan."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Nevažeća kartica."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Napunjeno"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • bežično punjenje"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brzo punjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • sporo punjenje"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Punjenje je privremeno ograničeno"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite punjač."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pritisnite Izbornik da biste otključali."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mreža je zaključana"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nema SIM kartice"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Zaporka uređaja"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Područje PIN-a za SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Područje PUK-a za SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Sljedeći alarm postavljen za <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Izbriši"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Onemogući eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Nije moguće onemogućiti eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Onemogućivanje eSIM-a nije uspjelo zbog pogreške."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Unos"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Zaboravili ste uzorak"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Pogrešan uzorak"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Pogrešna zaporka"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Pogrešan PIN"</string>
@@ -69,12 +57,9 @@
       <item quantity="few">Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekunde</item>
       <item quantity="other">Pokušajte ponovo za <xliff:g id="NUMBER">%d</xliff:g> sekundi</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Iscrtajte svoj uzorak"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Unesite PIN za SIM"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Unesite PIN za SIM mobilnog operatera \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Onemogućite eSIM kako biste uređaj upotrebljavali bez mobilne usluge."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Unesite PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Unesite zaporku"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM je sad onemogućen. Unesite PUK kôd da biste nastavili. Obratite se mobilnom operateru za više pojedinosti."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM mobilnog operatera \"<xliff:g id="CARRIER">%1$s</xliff:g>\" sada je onemogućen. Unesite PUK kôd da biste nastavili. Obratite se mobilnom operateru za više pojedinosti."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Unesite željeni PIN kôd"</string>
@@ -82,8 +67,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Otključavanje SIM kartice…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Unesite PIN koji ima od 4 do 8 brojeva."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kôd treba imati 8 brojeva ili više."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Ponovo unesite ispravan PUK kôd. Ponovljeni pokušaji trajno će onemogućiti SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Previše pokušaja iscrtavanja uzorka"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Netočno ste unijeli PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Netočno ste unijeli zaporku <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Netočno ste iscrtali uzorak za otključavanje <xliff:g id="NUMBER_0">%1$d</xliff:g> put/a. \n\nPokušajte ponovo za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
@@ -101,8 +84,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Operacija PIN-a SIM kartice nije uspjela!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Operacija PUK-a SIM kartice nije uspjela!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kôd je prihvaćen!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Nema usluge."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Promjena načina unosa"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Način rada u zrakoplovu"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Nakon ponovnog pokretanja uređaja morate unijeti uzorak"</string>
@@ -111,26 +92,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Unesite uzorak radi dodatne sigurnosti"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Unesite PIN radi dodatne sigurnosti"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Unesite zaporku radi dodatne sigurnosti"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Za promjenu profila morate unijeti uzorak"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Za promjenu profila morate unijeti PIN"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Za promjenu profila morate unijeti zaporku"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administrator je zaključao uređaj"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Uređaj je ručno zaključan"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Uređaj nije bio otključan <xliff:g id="NUMBER_1">%d</xliff:g> sat. Potvrdite uzorak.</item>
-      <item quantity="few">Uređaj nije bio otključan <xliff:g id="NUMBER_1">%d</xliff:g> sata. Potvrdite uzorak.</item>
-      <item quantity="other">Uređaj nije bio otključan <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite uzorak.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Uređaj nije bio otključan <xliff:g id="NUMBER_1">%d</xliff:g> sat. Potvrdite PIN.</item>
-      <item quantity="few">Uređaj nije bio otključan <xliff:g id="NUMBER_1">%d</xliff:g> sata. Potvrdite PIN.</item>
-      <item quantity="other">Uređaj nije bio otključan <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Uređaj nije bio otključan <xliff:g id="NUMBER_1">%d</xliff:g> sat. Potvrdite zaporku.</item>
-      <item quantity="few">Uređaj nije bio otključan <xliff:g id="NUMBER_1">%d</xliff:g> sata. Potvrdite zaporku.</item>
-      <item quantity="other">Uređaj nije bio otključan <xliff:g id="NUMBER_1">%d</xliff:g> sati. Potvrdite zaporku.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nije prepoznat"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nije prepoznato"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-hu/strings.xml b/packages/SystemUI/res-keyguard/values-hu/strings.xml
index 8f66c08..47b49a4 100644
--- a/packages/SystemUI/res-keyguard/values-hu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hu/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Billentyűzár"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Írja be a PIN-kódot"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Írja be a SIM-kártya PUK-kódját, majd az új PIN-kódot"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM-kártya PUK-kódja"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Új PIN-kód a SIM-kártyához"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Érintse meg jelszó megadásához"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"A feloldáshoz írja be a jelszót"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"A feloldáshoz írja be a PIN-kódot"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Adja meg PIN-kódját"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Adja meg a mintáját"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Adja meg jelszavát"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Helytelen PIN-kód."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Érvénytelen kártya."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Feltöltve"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Vezeték nélküli töltés"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Gyors töltés"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lassú töltés"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Töltés ideiglenesen korlátozva"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Csatlakoztassa a töltőt."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"A feloldáshoz nyomja meg a Menü gombot."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Hálózat zárolva"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nincs SIM-kártya"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Eszköz jelszava"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"A SIM-kártyához tartozó PIN-kód mezője"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"A SIM-kártyához tartozó PUK-kód mezője"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"A következő ébresztés beállított ideje: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Törlés"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Az e-SIM-kártya letiltása"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Nem lehet letiltani az eSIM-et"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Hiba történt, így az eSIM-et nem lehet letiltani."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Elfelejtettem a mintát"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Helytelen minta"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Helytelen jelszó"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Helytelen PIN-kód"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Próbálja újra <xliff:g id="NUMBER">%d</xliff:g> másodperc múlva.</item>
       <item quantity="one">Próbálja újra 1 másodperc múlva.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Rajzolja le a mintát"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Adja meg a SIM-kártya PIN-kódját."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Adja meg a(z) „<xliff:g id="CARRIER">%1$s</xliff:g>” SIM-kártya PIN-kódját."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Tiltsa le az e-SIM-et az eszköz mobilszolgáltatás nélküli használatához."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Adja meg a PIN-kódot"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Írja be a jelszót"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"A SIM-kártya le van tiltva. A folytatáshoz adja meg a PUK-kódot. A részletekért vegye fel a kapcsolatot szolgáltatójával."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"A(z) „<xliff:g id="CARRIER">%1$s</xliff:g>” SIM-kártya le van tiltva. A folytatáshoz adja meg a PUK-kódot. A részletekért vegye fel a kapcsolatot szolgáltatójával."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Adja meg a kívánt PIN-kódot"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM-kártya zárolásának feloldása…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Írjon be egy 4-8 számjegyű PIN-kódot."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"A PUK-kódnak legalább nyolc számjegyből kell állnia."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Adja meg újra a helyes PUK-kódot. Az ismételt próbálkozásokkal véglegesen letiltja a SIM-kártyát."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Túl sok mintarajzolási próbálkozás"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül adta meg a PIN-kódot.\n\nPróbálja újra <xliff:g id="NUMBER_1">%2$d</xliff:g> másodperc múlva."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal helytelenül adta meg a jelszót.\n\nPróbálja újra <xliff:g id="NUMBER_1">%2$d</xliff:g> másodperc múlva."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"<xliff:g id="NUMBER_0">%1$d</xliff:g> alkalommal rosszul rajzolta le a feloldási mintát.\n\nPróbálja újra <xliff:g id="NUMBER_1">%2$d</xliff:g> másodperc múlva."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"A SIM-kártya PIN-művelete sikertelen!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"A SIM-kártya PUK-művelete sikertelen!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kód elfogadva."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Nincs szolgáltatás."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Beviteli módszer váltása"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Repülős üzemmód"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Az eszköz újraindítását követően meg kell adni a mintát"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"A nagyobb biztonság érdekében minta szükséges"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"A nagyobb biztonság érdekében PIN-kód szükséges"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"A nagyobb biztonság érdekében jelszó szükséges"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Ha vált a profilok között, meg kell adni a mintát"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Ha vált a profilok között, meg kell adni a PIN-kódot"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Ha vált a profilok között, meg kell adni a jelszót"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"A rendszergazda zárolta az eszközt"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Az eszközt manuálisan lezárták"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Az eszköz zárolása <xliff:g id="NUMBER_1">%d</xliff:g> órája nem lett feloldva. Erősítse meg a mintát.</item>
-      <item quantity="one">Az eszköz zárolása <xliff:g id="NUMBER_0">%d</xliff:g> órája nem lett feloldva. Erősítse meg a mintát.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Az eszköz zárolása <xliff:g id="NUMBER_1">%d</xliff:g> órája nem lett feloldva. Erősítse meg a PIN-kódot.</item>
-      <item quantity="one">Az eszköz zárolása <xliff:g id="NUMBER_0">%d</xliff:g> órája nem lett feloldva. Erősítse meg a PIN-kódot.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Az eszköz zárolása <xliff:g id="NUMBER_1">%d</xliff:g> órája nem lett feloldva. Erősítse meg a jelszót.</item>
-      <item quantity="one">Az eszköz zárolása <xliff:g id="NUMBER_0">%d</xliff:g> órája nem lett feloldva. Erősítse meg a jelszót.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nem ismerhető fel"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nem ismerhető fel"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-hy/strings.xml b/packages/SystemUI/res-keyguard/values-hy/strings.xml
index f91a064..16bbb07 100644
--- a/packages/SystemUI/res-keyguard/values-hy/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-hy/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Մուտքագրեք PIN կոդը"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Մուտքագրեք SIM PUK և նոր PIN կոդերը"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK կոդը"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Նոր SIM PIN կոդը"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Հպեք` գաղտնաբառը մուտքագրելու համար"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Ապակողպելու համար մուտքագրեք գաղտնաբառը"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Ապակողպելու համար մուտքագրեք PIN կոդը"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Մուտքագրեք PIN կոդը"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Մուտքագրեք նախշը"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Մուտքագրեք գաղտնաբառը"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN կոդը սխալ է։"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Սխալ քարտ"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Լիցքավորված է"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Անլար լիցքավորում"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Արագ լիցքավորում"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Դանդաղ լիցքավորում"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Լիցքավորումը ժամանակավորապես սահմանափակված է"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Միացրեք լիցքավորիչը:"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ապակողպելու համար սեղմեք Ընտրացանկը:"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ցանցը կողպված է"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM քարտ չկա"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Սարքի գաղտնաբառ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM քարտի PIN կոդի տարածք"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM քարտի PUK կոդի տարածք"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Հաջորդ զարթուցիչը դրված է <xliff:g id="ALARM">%1$s</xliff:g>-ի վրա"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Ջնջել"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Անջատել էլեկտրոնային SIM քարտը"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Չհաջողվեց անջատել eSIM-ը"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Սխալի պատճառով չհաջողվեց անջատել eSIM-ը։"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Մուտքի ստեղն"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Մոռացել եմ նախշը"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Նախշը սխալ է"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Գաղտնաբառը սխալ է"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN կոդը սխալ է"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">Փորձեք <xliff:g id="NUMBER">%d</xliff:g> վայրկյանից:</item>
       <item quantity="other">Փորձեք <xliff:g id="NUMBER">%d</xliff:g> վայրկյանից:</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Մուտքագրեք նախշը"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Մուտքագրեք SIM քարտի PIN կոդը։"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Մուտքագրեք SIM քարտի PIN կոդը «<xliff:g id="CARRIER">%1$s</xliff:g>»-ի համար:"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Անջատեք eSIM-ը՝ սարքն առանց բջջային կապի օգտագործելու համար։"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Մուտքագրեք PIN-ը"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Մուտքագրեք գաղտնաբառը"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM քարտն այժմ անջատված է: Շարունակելու համար մուտքագրեք PUK կոդը: Մանրամասն տեղեկություններ ստանալու համար դիմեք օպերատորին:"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"«<xliff:g id="CARRIER">%1$s</xliff:g>» SIM քարտն այժմ անջատված է: Շարունակելու համար մուտքագրեք PUK կոդը: Մանրամասն տեղեկություններ ստանալու համար դիմեք օպերատորին:"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Մուտքագրեք ցանկալի PIN կոդը"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM քարտն ապակողպվում է…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Մուտքագրեք 4-8 թվանշան պարունակող PIN կոդ։"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK կոդը պետք է առնվազն 8 թվանշան պարունակի։"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Վերամուտքագրեք ճիշտ PUK կոդը: Կրկնվող փորձերը ընդմիշտ կարգելափակեն SIM քարտը:"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Նախշը մուտքագրելու չափազանց շատ փորձեր են կատարվել"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Դուք սխալ եք մուտքագրել ձեր PIN կոդը <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ: \n\nՓորձեք կրկին <xliff:g id="NUMBER_1">%2$d</xliff:g> վայրկյանից։"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Դուք սխալ եք մուտքագրել ձեր գաղտնաբառը <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ: \n\nՓորձեք կրկին <xliff:g id="NUMBER_1">%2$d</xliff:g> վայրկյանից:"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Դուք սխալ եք մուտքագրել ձեր ապակողպման նախշը <xliff:g id="NUMBER_0">%1$d</xliff:g> անգամ: \n\nՓորձեք կրկին <xliff:g id="NUMBER_1">%2$d</xliff:g> վայրկյանից։"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN կոդի գործողությունը ձախողվեց:"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK կոդի գործողությունը ձախողվեց:"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Կոդն ընդունվեց:"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Ծառայությունն անհասանելի է։"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Փոխել ներածման եղանակը"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Ավիառեժիմ"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Սարքը վերագործարկելուց հետո անհրաժեշտ է մուտքագրել նախշը"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Անվտանգության նկատառումներից ելնելով անհրաժեշտ է մուտքագրել նախշը"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Անվտանգության նկատառումներից ելնելով անհրաժեշտ է մուտքագրել PIN կոդը"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Անվտանգության նկատառումներից ելնելով անհրաժեշտ է մուտքագրել գաղտնաբառը"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Պրոֆիլները փոխարկելիս անհրաժեշտ է մուտքագրել նախշը"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Պրոֆիլները փոխարկելիս անհրաժեշտ է մուտքագրել PIN կոդը"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Պրոֆիլները փոխարկելիս անհրաժեշտ է մուտքագրել գաղտնաբառը"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Սարքը կողպված է ադմինիստրատորի կողմից"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Սարքը կողպվել է ձեռքով"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Սարքը չի ապակողպվել <xliff:g id="NUMBER_1">%d</xliff:g> ժամվա ընթացքում: Հաստատեք նախշը:</item>
-      <item quantity="other">Սարքը չի ապակողպվել <xliff:g id="NUMBER_1">%d</xliff:g> ժամվա ընթացքում: Հաստատեք նախշը:</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Սարքը չի ապակողպվել <xliff:g id="NUMBER_1">%d</xliff:g> ժամվա ընթացքում: Հաստատեք PIN կոդը:</item>
-      <item quantity="other">Սարքը չի ապակողպվել <xliff:g id="NUMBER_1">%d</xliff:g> ժամվա ընթացքում: Հաստատեք PIN կոդը:</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Սարքը չի ապակողպվել <xliff:g id="NUMBER_1">%d</xliff:g> ժամվա ընթացքում: Հաստատեք գաղտնաբառը:</item>
-      <item quantity="other">Սարքը չի ապակողպվել <xliff:g id="NUMBER_1">%d</xliff:g> ժամվա ընթացքում: Հաստատեք գաղտնաբառը:</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Չհաջողվեց ճանաչել"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Չհաջողվեց ճանաչել"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-in/strings.xml b/packages/SystemUI/res-keyguard/values-in/strings.xml
index edf8ab2..757e6a5 100644
--- a/packages/SystemUI/res-keyguard/values-in/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-in/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Ketik kode PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Ketik kode PIN baru dan PUK SIM"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Kode PUK SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Kode PIN SIM baru"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Sentuh untuk mengetik sandi"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Ketik sandi untuk membuka kunci"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Ketik PIN untuk membuka kunci"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Masukkan PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Masukkan pola"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Masukkan sandi"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Kode PIN salah."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Kartu Tidak Valid"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Terisi penuh"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya secara nirkabel"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan cepat"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengisi daya dengan lambat"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengisian daya dibatasi sementara"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Hubungkan pengisi daya."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Jaringan terkunci"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Tidak ada kartu SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Sandi perangkat"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Bidang PIN SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Bidang PUK SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Alarm berikutnya disetel untuk <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Hapus"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Nonaktifkan eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Tidak dapat menonaktifkan eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM tidak dapat dinonaktifkan karena terjadi error."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Masukkan"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Lupa Pola?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Pola salah"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Sandi salah"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN Salah"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Coba <xliff:g id="NUMBER">%d</xliff:g> detik lagi.</item>
       <item quantity="one">Coba 1 detik lagi.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Gambar pola Anda"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Masukkan PIN SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Masukkan PIN SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Nonaktifkan eSIM untuk menggunakan perangkat tanpa layanan seluler."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Masukkan PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Masukkan Sandi"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM telah dinonaktifkan. Masukkan kode PUK untuk melanjutkan. Hubungi operator untuk keterangan selengkapnya."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" kini dinonaktifkan. Masukkan kode PUK untuk melanjutkan. Hubungi operator untuk mengetahui detailnya."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Masukkan kode PIN yang diinginkan"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Membuka kunci kartu SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Ketikkan PIN berupa 4 sampai 8 angka."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Kode PUK harus terdiri dari 8 angka atau lebih."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Masukkan kembali kode PUK yang benar. Jika berulang kali gagal, SIM akan dinonaktifkan secara permanen."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Terlalu banyak upaya pola"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah mengetik PIN. \n\nCoba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> detik."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah mengetik sandi. \n\nCoba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> detik."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali salah menggambar pola pembuka kunci. \n\nCoba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> detik."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Operasi PIN SIM gagal!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Operasi PUK SIM gagal!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kode Diterima!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Tidak ada layanan."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Beralih metode input"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Mode pesawat"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pola diperlukan setelah perangkat dimulai ulang"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Pola diperlukan untuk keamanan tambahan"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN diperlukan untuk keamanan tambahan"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Sandi diperlukan untuk keamanan tambahan"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Pola diperlukan jika Anda beralih profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PIN diperlukan jika Anda beralih profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Sandi diperlukan jika Anda beralih profil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Perangkat dikunci oleh admin"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Perangkat dikunci secara manual"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Perangkat belum dibuka kuncinya selama <xliff:g id="NUMBER_1">%d</xliff:g> jam. Konfirmasi pola.</item>
-      <item quantity="one">Perangkat belum dibuka kuncinya selama <xliff:g id="NUMBER_0">%d</xliff:g> jam. Konfirmasi pola.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Perangkat belum dibuka kuncinya selama <xliff:g id="NUMBER_1">%d</xliff:g> jam. Konfirmasi PIN.</item>
-      <item quantity="one">Perangkat belum dibuka kuncinya selama <xliff:g id="NUMBER_0">%d</xliff:g> jam. Konfirmasi PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Perangkat belum dibuka kuncinya selama <xliff:g id="NUMBER_1">%d</xliff:g> jam. Konfirmasi sandi.</item>
-      <item quantity="one">Perangkat belum dibuka kuncinya selama <xliff:g id="NUMBER_0">%d</xliff:g> jam. Konfirmasi sandi.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Tidak dikenali"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Tidak dikenali"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-is/strings.xml b/packages/SystemUI/res-keyguard/values-is/strings.xml
index d1436b9..6dc8246 100644
--- a/packages/SystemUI/res-keyguard/values-is/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-is/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Takkavörn"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Sláðu inn PIN-númer"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Sláðu inn PUK-númer SIM-korts og nýtt PIN-númer"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK-númer SIM-korts"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nýtt PIN-númer SIM-korts"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Snertu og sláðu inn aðgangsorð"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Sláðu inn aðgangsorðið til að opna"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Sláðu inn PIN-númer til að opna"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Sláðu inn PIN-númer"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Færðu inn mynstrið þitt"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Sláðu inn aðgangsorðið þitt"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Rangt PIN-númer."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ógilt kort."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Fullhlaðin"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Í þráðlausri hleðslu"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hröð hleðsla"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hæg hleðsla"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hleðsla takmörkuð tímabundið"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Tengdu hleðslutækið."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ýttu á valmyndarhnappinn til að taka úr lás."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Net læst"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Ekkert SIM-kort"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Aðgangsorð tækis"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"PIN-svæði SIM-korts"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"PUK-svæði SIM-korts"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Næsti vekjari stilltur á <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Eyða"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Aftengja eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Ekki tókst að gera eSIM-kort óvirkt"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Villa kom í veg fyrir að hægt væri að gera eSIM-kortið óvirkt."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Færa inn"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Man ekki mynstrið"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Rangt mynstur"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Rangt aðgangsorð"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Rangt PIN-númer"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">Reyndu aftur eftir <xliff:g id="NUMBER">%d</xliff:g> sekúndu.</item>
       <item quantity="other">Reyndu aftur eftir <xliff:g id="NUMBER">%d</xliff:g> sekúndur.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Teiknaðu mynstrið þitt"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Sláðu inn PIN-númer SIM-kortsins."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Sláðu inn PIN-númer SIM-korts fyrir „<xliff:g id="CARRIER">%1$s</xliff:g>“."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Gerðu eSIM-kortið óvirkt til að nota tækið án tengingar við farsímakerfi."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Sláðu inn PIN-númer"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Sláðu inn aðgangsorð"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM-kortið hefur verið gert óvirkt. Sláðu inn PUK-númerið til að halda áfram. Hafðu samband við símafyrirtækið til að fá frekari upplýsingar."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM-kortið „<xliff:g id="CARRIER">%1$s</xliff:g>“ hefur verið gert óvirkt. Sláðu inn PUK-númerið til að halda áfram. Hafðu samband við símafyrirtækið til að fá frekari upplýsingar."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Sláðu inn nýtt PIN-númer"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Tekur SIM-kort úr lás…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Sláðu in PIN-númer sem er 4 til 8 tölustafir."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-númerið verður að vera 8 tölustafir eða lengra."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Prófaðu aftur að setja inn rétt PUK-númer. Endurteknar tilraunir gera SIM-kortið varanlega óvirkt."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Of margar tilraunir til að teikna mynstur"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Þú hefur slegið inn rangt PIN-númer <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. \n\nReyndu aftur eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> sekúndur."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Þú hefur slegið inn rangt aðgangsorð <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. \n\nReyndu aftur eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> sekúndur."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Þú hefur teiknað rangt opnunarmynstur <xliff:g id="NUMBER_0">%1$d</xliff:g> sinnum. \n\nReyndu aftur eftir <xliff:g id="NUMBER_1">%2$d</xliff:g> sekúndur."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"PIN-aðgerð SIM-korts mistókst!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"PUK-aðgerð SIM-korts mistókst!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Númer samþykkt!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Ekkert símasamband."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Skipta um innsláttaraðferð"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Flugstilling"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Mynsturs er krafist þegar tækið er endurræst"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Mynsturs er krafist af öryggisástæðum"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN-númers er krafist af öryggisástæðum"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Aðgangsorðs er krafist af öryggisástæðum"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Mynsturs er krafist þegar þú skiptir um snið"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PIN-númers er krafist þegar þú skiptir um snið"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Aðgangsorðs er krafist þegar þú skiptir um snið"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Kerfisstjóri læsti tæki"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Tækinu var læst handvirkt"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Tækið hefur ekki verið tekið úr lás í <xliff:g id="NUMBER_1">%d</xliff:g> klukkustund. Staðfestu mynstrið.</item>
-      <item quantity="other">Tækið hefur ekki verið tekið úr lás í <xliff:g id="NUMBER_1">%d</xliff:g> klukkustundir. Staðfestu mynstrið.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Tækið hefur ekki verið tekið úr lás í <xliff:g id="NUMBER_1">%d</xliff:g> klukkustund. Staðfestu PIN-númerið.</item>
-      <item quantity="other">Tækið hefur ekki verið tekið úr lás í <xliff:g id="NUMBER_1">%d</xliff:g> klukkustundir. Staðfestu PIN-númerið.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Tækið hefur ekki verið tekið úr lás í <xliff:g id="NUMBER_1">%d</xliff:g> klukkustund. Staðfestu aðgangsorðið.</item>
-      <item quantity="other">Tækið hefur ekki verið tekið úr lás í <xliff:g id="NUMBER_1">%d</xliff:g> klukkustundir. Staðfestu aðgangsorðið.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Þekktist ekki"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Þekktist ekki"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml
index 0497c41..337d433 100644
--- a/packages/SystemUI/res-keyguard/values-it/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-it/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Inserisci il codice PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Digita il PUK della SIM e il nuovo codice PIN"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Codice PUK della SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nuovo PIN della SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Tocca per inserire la password"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Inserisci password per sbloccare"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Inserisci PIN per sbloccare"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Inserisci il PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Inserisci la sequenza"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Inserisci la password"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Codice PIN errato."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Scheda non valida."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Carico"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • In carica wireless"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica veloce"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica lenta"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ricarica momentaneamente limitata"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Collega il caricabatterie."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Premi Menu per sbloccare."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rete bloccata"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nessuna SIM"</string>
@@ -54,26 +44,21 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Password del dispositivo"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Area PIN SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Area PUK SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Prossima sveglia impostata a: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Elimina"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Disattiva eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Impossibile disattivare la eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Impossibile disattivare la eSIM a causa di un errore."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Invio"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Sequenza dimenticata"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Sequenza errata"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Password errata"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN errato"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914">
+      <item quantity="one">Try again in <xliff:g id="NUMBER">%d</xliff:g> seconds.</item>
       <item quantity="other">Riprova fra <xliff:g id="NUMBER">%d</xliff:g> secondi.</item>
-      <item quantity="one">Riprova fra 1 secondo.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Inserisci la sequenza"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Inserisci il PIN della SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Inserisci il PIN della SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disattiva la eSIM per usare il dispositivo senza servizio dati mobile."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Inserisci PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Inserisci la password"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"La scheda SIM è disattivata. Inserisci il codice PUK per continuare. Contatta l\'operatore per avere informazioni dettagliate."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"La SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" non è attiva al momento. Inserisci il codice PUK per continuare. Contatta l\'operatore per avere informazioni dettagliate."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Inserisci il codice PIN desiderato"</string>
@@ -81,25 +66,21 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Sblocco SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Il PIN deve essere di 4-8 numeri."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Il codice PUK dovrebbe avere almeno otto numeri."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Inserisci di nuovo il codice PUK corretto. Ripetuti tentativi comportano la disattivazione definitiva della scheda SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Troppi tentativi di inserimento della sequenza"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Hai digitato il tuo PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> volte in modo errato. \n\nRiprova tra <xliff:g id="NUMBER_1">%2$d</xliff:g> secondi."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Hai digitato la tua password <xliff:g id="NUMBER_0">%1$d</xliff:g> volte in modo errato. \n\nRiprova tra <xliff:g id="NUMBER_1">%2$d</xliff:g> secondi."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. \n\nRiprova tra <xliff:g id="NUMBER_1">%2$d</xliff:g> secondi."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Codice PIN della SIM errato. Devi contattare l\'operatore per sbloccare il dispositivo."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
+      <item quantity="one">Incorrect SIM PIN code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
       <item quantity="other">Codice PIN della SIM errato. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione.</item>
-      <item quantity="one">Codice PIN della SIM errato. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM inutilizzabile. Contatta il tuo operatore."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886">
+      <item quantity="one">Incorrect SIM PUK code, you have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable.</item>
       <item quantity="other">Codice PUK della SIM errato. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile.</item>
-      <item quantity="one">Codice PUK della SIM errato. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile.</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Operazione con PIN della SIM non riuscita."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Operazione con PUK della SIM non riuscita."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Codice accettato."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Nessun servizio."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Cambia metodo di immissione"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Modalità aereo"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Sequenza obbligatoria dopo il riavvio del dispositivo"</string>
@@ -108,32 +89,17 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Sequenza obbligatoria per maggiore sicurezza"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN obbligatorio per maggiore sicurezza"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Password obbligatoria per maggiore sicurezza"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Sequenza obbligatoria dopo aver cambiato profilo"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PIN obbligatorio dopo aver cambiato profilo"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Password obbligatoria dopo aver cambiato profilo"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloccato dall\'amministratore"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Il dispositivo è stato bloccato manualmente"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Il dispositivo non viene sbloccato da <xliff:g id="NUMBER_1">%d</xliff:g> ore. Conferma la sequenza.</item>
-      <item quantity="one">Il dispositivo non viene sbloccato da <xliff:g id="NUMBER_0">%d</xliff:g> ora. Conferma la sequenza.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Il dispositivo non viene sbloccato da <xliff:g id="NUMBER_1">%d</xliff:g> ore. Conferma il PIN.</item>
-      <item quantity="one">Il dispositivo non viene sbloccato da <xliff:g id="NUMBER_0">%d</xliff:g> ora. Conferma il PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Il dispositivo non viene sbloccato da <xliff:g id="NUMBER_1">%d</xliff:g> ore. Conferma la password.</item>
-      <item quantity="one">Il dispositivo non viene sbloccato da <xliff:g id="NUMBER_0">%d</xliff:g> ora. Conferma la password.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Non riconosciuto"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Non riconosciuto"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
+      <item quantity="one">Enter SIM PIN. You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts.</item>
       <item quantity="other">Inserisci il codice PIN della SIM. Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione.</item>
-      <item quantity="one">Inserisci il codice PIN della SIM. Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.</item>
     </plurals>
     <plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935">
+      <item quantity="one">SIM is now disabled. Enter PUK code to continue. You have <xliff:g id="_NUMBER_1">%d</xliff:g> remaining attempts before SIM becomes permanently unusable. Contact carrier for details.</item>
       <item quantity="other">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.</item>
-      <item quantity="one">La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora <xliff:g id="_NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.</item>
     </plurals>
     <string name="clock_title_default" msgid="6342735240617459864">"Predefinito"</string>
     <string name="clock_title_bubble" msgid="2204559396790593213">"Bolla"</string>
diff --git a/packages/SystemUI/res-keyguard/values-iw/strings.xml b/packages/SystemUI/res-keyguard/values-iw/strings.xml
index bbc5aa0..1ba6f83 100644
--- a/packages/SystemUI/res-keyguard/values-iw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-iw/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"מגן מקלדת"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"יש להזין את קוד האימות"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"‏יש להזין את קוד ה-PUK של כרטיס ה-SIM ולאחר מכן את קוד האימות חדש"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"‏קוד PUK של כרטיס SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"‏קוד אימות חדש לכרטיס ה-SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"צריך לגעת כדי להקליד את הסיסמה"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"יש להזין סיסמה לביטול הנעילה"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"יש להזין את קוד האימות לביטול הנעילה"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"צריך להזין קוד אימות"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"יש להזין קו ביטול נעילה"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"יש להזין סיסמה"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"קוד האימות שגוי"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"כרטיס לא חוקי."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"הסוללה טעונה"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה אלחוטית"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה מהירה"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • בטעינה איטית"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • הטעינה מוגבלת באופן זמני"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"כדאי לחבר את המטען."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"יש ללחוץ על \'תפריט\' כדי לבטל את הנעילה."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"הרשת נעולה"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"‏אין כרטיס SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"סיסמת המכשיר"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"‏אזור לקוד האימות של כרטיס ה-SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"‏האזור של קוד האימות של כרטיס ה-SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"ההתראה הבאה נקבעה ל-<xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Delete"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"‏השבתת ה-eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"‏לא ניתן להשבית את כרטיס ה-eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"‏לא ניתן להשבית את כרטיס ה-eSIM עקב שגיאה."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"שכחתי את קו ביטול הנעילה"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"קו ביטול נעילה שגוי"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"סיסמה שגויה"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"קוד האימות שגוי"</string>
@@ -70,12 +58,9 @@
       <item quantity="other">אפשר יהיה לנסות שוב בעוד <xliff:g id="NUMBER">%d</xliff:g> שניות.</item>
       <item quantity="one">אפשר יהיה לנסות שוב בעוד שנייה אחת.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"צריך לשרטט את קו ביטול הנעילה"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"‏יש להזין את קוד האימות של כרטיס ה-SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"‏יש להזין את קוד האימות של כרטיס ה-SIM של <xliff:g id="CARRIER">%1$s</xliff:g>."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"‏<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> יש להשבית את כרטיס ה-eSIM כדי להשתמש במכשיר ללא שירות סלולרי."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"יש להזין קוד אימות"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"צריך להזין את הסיסמה"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"‏כרטיס ה-SIM מושבת עכשיו. צריך להזין קוד PUK כדי להמשיך. יש לפנות אל הספק לקבלת פרטים."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"‏ה-SIM של \"<xliff:g id="CARRIER">%1$s</xliff:g>\" מושבת עכשיו. צריך להזין קוד PUK כדי להמשיך. לפרטים, יש לפנות אל הספק."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"יש להזין את קוד האימות הרצוי"</string>
@@ -83,8 +68,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"‏מתבצע ביטול נעילה של כרטיס ה-SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"יש להקליד קוד אימות שאורכו 4 עד 8 ספרות."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"‏קוד PUK צריך להיות בן 8 ספרות או יותר."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"‏יש להזין את קוד ה-PUK הנכון. ניסיונות חוזרים ישביתו את כרטיס ה-SIM באופן סופי."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"ניסית לשרטט את קו ביטול הנעילה יותר מדי פעמים"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"הקלדת קוד גישה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nיש לנסות שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"הקלדת סיסמה שגויה <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nאפשר לנסות שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"שרטטת קו ביטול נעילה שגוי <xliff:g id="NUMBER_0">%1$d</xliff:g> פעמים. \n\nאפשר לנסות שוב בעוד <xliff:g id="NUMBER_1">%2$d</xliff:g> שניות."</string>
@@ -104,8 +87,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"‏נכשלה פעולת קוד הגישה של כרטיס ה-SIM"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"‏הניסיון לביטול הנעילה של כרטיס ה-SIM באמצעות קוד PUK נכשל!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"הקוד התקבל!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"אין שירות."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"החלפת שיטת קלט"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"מצב טיסה"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"יש להזין את קו ביטול הנעילה לאחר הפעלה מחדש של המכשיר"</string>
@@ -114,29 +95,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"יש להזין את קו ביטול הנעילה כדי להגביר את רמת האבטחה"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"יש להזין קוד אימות כדי להגביר את רמת האבטחה"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"יש להזין סיסמה כדי להגביר את רמת האבטחה"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"יש להזין את קו ביטול הנעילה כשמחליפים בין פרופילים"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"צריך להזין את קוד האימות כשמחליפים פרופיל"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"יש להזין את הסיסמה בזמן מעבר בין פרופילים"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"המנהל של המכשיר נהל אותו"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"המכשיר ננעל באופן ידני"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="two">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את קו ביטול הנעילה.</item>
-      <item quantity="many">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את קו ביטול הנעילה.</item>
-      <item quantity="other">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את קו ביטול הנעילה.</item>
-      <item quantity="one">נעילת המכשיר לא בוטלה במשך שעה אחת (<xliff:g id="NUMBER_0">%d</xliff:g>). יש להזין את קו ביטול הנעילה.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="two">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את קוד האימות.</item>
-      <item quantity="many">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את קוד האימות.</item>
-      <item quantity="other">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את קוד האימות.</item>
-      <item quantity="one">נעילת המכשיר לא בוטלה במשך שעה (<xliff:g id="NUMBER_0">%d</xliff:g>). יש להזין את קוד האימות.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="two">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את הסיסמה.</item>
-      <item quantity="many">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את הסיסמה.</item>
-      <item quantity="other">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_1">%d</xliff:g> שעות. יש להזין את הסיסמה.</item>
-      <item quantity="one">נעילת המכשיר לא בוטלה במשך <xliff:g id="NUMBER_0">%d</xliff:g> שעה. יש להזין את הסיסמה.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"לא זוהתה"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"לא זוהתה"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ja/strings.xml b/packages/SystemUI/res-keyguard/values-ja/strings.xml
index 60b52ea..1acc14c 100644
--- a/packages/SystemUI/res-keyguard/values-ja/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ja/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"キーガード"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"PIN コードを入力してください"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM PUK と新しい PIN コードを入力してください"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK コード"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"新しい SIM PIN コード"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"タップしてパスワードを入力"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"ロックを解除するにはパスワードを入力してください"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"ロックを解除するには PIN を入力してください"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"PIN を入力してください"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"パターンを入力してください"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"パスワードを入力してください"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN コードが無効です。"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"無効なカードです。"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"充電が完了しました"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ワイヤレス充電中"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 急速充電中"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 低速充電中"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電を一時的に制限しています"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"充電してください。"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"メニューからロックを解除できます。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ネットワークがロックされました"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM カードなし"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"デバイスのパスワード"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN エリア"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK エリア"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"次のアラームを <xliff:g id="ALARM">%1$s</xliff:g> に設定しました"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"削除"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM を無効にする"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM を無効にできません"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"エラーのため、eSIM を無効にできません。"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"入力"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"パターンを忘れた場合"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"パターンが正しくありません"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"パスワードが正しくありません"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN が正しくありません"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> 秒後にもう一度お試しください。</item>
       <item quantity="one">1 秒後にもう一度お試しください。</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"パターンを入力してください"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM PIN を入力してください。"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"「<xliff:g id="CARRIER">%1$s</xliff:g>」の SIM PIN を入力してください。"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g>モバイル サービスなしでデバイスを使用するには eSIM を無効にしてください。"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"PIN を入力してください"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"パスワードを入力してください"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM が無効になりました。続行するには PUK コードを入力してください。詳しくは携帯通信会社にお問い合わせください。"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM「<xliff:g id="CARRIER">%1$s</xliff:g>」が無効になりました。続行するには PUK コードを入力してください。詳しくは携帯通信会社にお問い合わせください。"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"必要な PIN コードを入力してください"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM カードのロックを解除しています…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"PIN は 4~8 桁の数字で入力してください。"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK コードは 8 桁以下の数字で入力してください。"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"正しい PUK コードを再入力してください。誤入力を繰り返すと、SIM が完全に無効になる恐れがあります。"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"パターンの入力を所定の回数以上間違えました"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN の入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後にもう一度お試しください。"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"パスワードの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後にもう一度お試しください。"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ロック解除パターンの入力を <xliff:g id="NUMBER_0">%1$d</xliff:g> 回間違えました。\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後にもう一度お試しください。"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN 操作に失敗しました。"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK 操作に失敗しました。"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"コードが承認されました。"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"通信サービスはありません。"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"入力方法の切り替え"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"機内モード"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"デバイスの再起動後はパターンの入力が必要となります"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"追加の確認のためパターンが必要です"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"追加の確認のため PIN が必要です"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"追加の確認のためパスワードが必要です"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"プロファイルを切り替えるにはパターンが必要です"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"プロファイルを切り替えるには PIN が必要です"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"プロファイルを切り替えるにはパスワードが必要です"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"デバイスは管理者によりロックされています"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"デバイスは手動でロックされました"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">デバイスのロックが <xliff:g id="NUMBER_1">%d</xliff:g> 時間、解除されていません。パターンを確認してください。</item>
-      <item quantity="one">デバイスのロックが <xliff:g id="NUMBER_0">%d</xliff:g> 時間、解除されていません。パターンを確認してください。</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">デバイスのロックが <xliff:g id="NUMBER_1">%d</xliff:g> 時間、解除されていません。PIN を確認してください。</item>
-      <item quantity="one">デバイスのロックが <xliff:g id="NUMBER_0">%d</xliff:g> 時間、解除されていません。PIN を確認してください。</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">デバイスのロックが <xliff:g id="NUMBER_1">%d</xliff:g> 時間、解除されていません。パスワードを確認してください。</item>
-      <item quantity="one">デバイスのロックが <xliff:g id="NUMBER_0">%d</xliff:g> 時間、解除されていません。パスワードを確認してください。</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"認識されませんでした"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"認識されませんでした"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ka/strings.xml b/packages/SystemUI/res-keyguard/values-ka/strings.xml
index 509c219..2f38e64 100644
--- a/packages/SystemUI/res-keyguard/values-ka/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ka/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"აკრიფეთ PIN-კოდი"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"აკრიფეთ SIM ბარათის PUK-კოდი და ახალი PIN-კოდი"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM ბარათის PUK-კოდი"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"SIM ბარათის ახალი PIN-კოდი"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"შეეხეთ პაროლის ასაკრეფად"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"განსაბლოკად აკრიფეთ პაროლი"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"განსაბლოკად აკრიფეთ PIN-კოდი"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"შეიყვანეთ PIN-კოდი"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"შეიყვანეთ განმბლოკავი ნიმუში"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"შეიყვანეთ პაროლი"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN-კოდი არასწორია."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ბარათი არასწორია."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"დატენილია"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • იტენება უსადენოდ"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • სწრაფად იტენება"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ნელა იტენება"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • დატენვა დროებით შეზღუდულია"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"შეაერთეთ დამტენი."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"განსაბლოკად დააჭირეთ მენიუს."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ქსელი ჩაკეტილია"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM ბარ. არაა"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"მოწყობილობის პაროლი"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM ბარათის PIN-კოდის არე"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM ბარათის PUK-კოდის არე"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"შემდეგი მაღვიძარა დაყენებულია <xliff:g id="ALARM">%1$s</xliff:g>-ზე"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"წაშლა"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM-ის გათიშვა"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM-ის გათიშვა ვერ ხერხდება"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM-ის გათიშვა ვერ ხერხდება წარმოქმნილი შეცდომის გამო."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"შეყვანა"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"დაგავიწყდათ ნიმუში"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"ნიმუში არასწორია"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"პაროლი არასწორია"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN-კოდი არასწორია"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">ცადეთ ხელახლა <xliff:g id="NUMBER">%d</xliff:g> წამში.</item>
       <item quantity="one">ცადეთ ხელახლა 1 წამში.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"დახატეთ თქვენი ნიმუში"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"შეიყვანეთ SIM ბარათის PIN-კოდი."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"შეიყვანეთ SIM ბარათის PIN-კოდი „<xliff:g id="CARRIER">%1$s</xliff:g>“-ისთვის."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> გათიშეთ eSIM, მოწყობილობის მობილური სერვისების გარეშე გამოსაყენებლად."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"შეიყვანეთ PIN-კოდი"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"შეიყვანეთ პაროლი"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM ბარათი ახლა დეაქტივირებულია. გასაგრძელებლად შეიყვანეთ PUK-კოდი. დეტალური ინფორმაციისთვის დაუკავშირდით თქვენს ოპერატორს."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM ბარათი (<xliff:g id="CARRIER">%1$s</xliff:g>) ახლა დეაქტივირებულია. გასაგრძელებლად შეიყვანეთ PUK-კოდი. დეტალური ინფორმაციისთვის დაუკავშირდით თქვენს ოპერატორს."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"შეიყვანეთ სასურველი PIN-კოდი"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"მიმდინარეობს SIM ბარათის განბლოკვა…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"აკრიფეთ 4-8 ციფრისგან შემდგარი PIN-კოდი."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-კოდი 8 ან მეტი ციფრისგან უნდა შედგებოდეს."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"ხელახლა შეიყვანეთ სწორი PUK-კოდი. რამდენიმე წარუმატებელი მცდელობის შემთხვევაში, SIM ბარათი სამუდამოდ გამოუსადეგარი გახდება."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"ნიმუში დახატულია არასწორად მეტისმეტად ბევრჯერ"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"თქვენ არასწორად შეიყვანეთ PIN-კოდი <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. \n\nცადეთ ხელახლა <xliff:g id="NUMBER_1">%2$d</xliff:g> წამში."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"თქვენ არასწორად აკრიფეთ პაროლი <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. \n\nცადეთ ხელახლა <xliff:g id="NUMBER_1">%2$d</xliff:g> წამში."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"თქვენ არასწორად დახატეთ განბლოკვის ნიმუში <xliff:g id="NUMBER_0">%1$d</xliff:g>-ჯერ. \n\nცადეთ ხელახლა <xliff:g id="NUMBER_1">%2$d</xliff:g> წამში."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM ბარათის PIN-კოდით განბლოკვა ვერ მოხერხდა!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM ბარათის PUK-კოდით განბლოკვა ვერ მოხერხდა!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"კოდი მიღებულია!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"სერვისი არ არის."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"შეყვანის მეთოდის გადართვა"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"თვითმფრინავის რეჟიმი"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"მოწყობილობის გადატვირთვის შემდეგ საჭიროა ნიმუშის დახატვა"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"დამატებითი უსაფრთხოებისთვის საჭიროა ნიმუშის დახატვა"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"დამატებითი უსაფრთხოებისთვის საჭიროა PIN-კოდის შეყვანა"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"დამატებითი უსაფრთხოებისთვის საჭიროა პაროლის შეყვანა"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"პროფილების გადართვისას საჭიროა ნიმუშის დახატვა"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"პროფილების გადართვისას საჭიროა PIN-კოდის შეყვანა"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"პროფილების გადართვისას საჭიროა პაროლის შეყვანა"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"მოწყობილობა ჩაკეტილია ადმინისტრატორის მიერ"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"მოწყობილობა ხელით ჩაიკეტა"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">მოწყობილობა არ განბლოკილა <xliff:g id="NUMBER_1">%d</xliff:g> საათის განმავლობაში. დაადასტურეთ ნიმუში.</item>
-      <item quantity="one">მოწყობილობა არ განბლოკილა <xliff:g id="NUMBER_0">%d</xliff:g> საათის განმავლობაში. დაადასტურეთ ნიმუში.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">მოწყობილობა არ განბლოკილა <xliff:g id="NUMBER_1">%d</xliff:g> საათის განმავლობაში. დაადასტურეთ PIN-კოდი.</item>
-      <item quantity="one">მოწყობილობა არ განბლოკილა <xliff:g id="NUMBER_0">%d</xliff:g> საათის განმავლობაში. დაადასტურეთ PIN-კოდი.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">მოწყობილობა არ განბლოკილა <xliff:g id="NUMBER_1">%d</xliff:g> საათის განმავლობაში. დაადასტურეთ პაროლი.</item>
-      <item quantity="one">მოწყობილობა არ განბლოკილა <xliff:g id="NUMBER_0">%d</xliff:g> საათის განმავლობაში. დაადასტურეთ პაროლი.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"არ არის ამოცნობილი"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"არ არის ამოცნობილი"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-kk/strings.xml b/packages/SystemUI/res-keyguard/values-kk/strings.xml
index 2993425..c7a1713 100644
--- a/packages/SystemUI/res-keyguard/values-kk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kk/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Пернелер қорғағышы"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"PIN кодын енгізіңіз"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM PUK кодын және жаңа PIN кодын енгізіңіз"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK коды"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Жаңа SIM PIN коды"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Құпия сөзді енгізу үшін түртіңіз"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Құлпын ашу үшін құпия сөзді теріңіз"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Құлпын ашу үшін PIN кодын енгізіңіз"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"PIN кодын енгізіңіз"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Өрнекті енгізіңіз"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Құпия сөзді енгізіңіз"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN коды қате"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Жарамсыз карта."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Зарядталды"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Сымсыз зарядталуда"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жылдам зарядталуда"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Баяу зарядталуда"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядтау уақытша шектелген"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Зарядтағышты қосыңыз."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Ашу үшін \"Мәзір\" пернесін басыңыз."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Желі құлыптаулы"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM картасы салынбаған"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Құрылғы құпия сөзі"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN аумағы"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK аумағы"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Келесі дабыл уақыты: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Жою"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM картасын өшіру"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM картасы өшірілмеді"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Қатеге байланысты eSIM картасы өшірілмеді."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Енгізу"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Өрнекті ұмытып қалдыңыз ба?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Өрнек дұрыс емес"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Құпия сөз дұрыс емес"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN коды қате"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"> <xliff:g id="NUMBER">%d</xliff:g> секундтан кейін қайталап көріңіз.</item>
       <item quantity="one">1 секундтан кейін қайталап көріңіз.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Өрнекті енгізіңіз"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM PIN кодын енгізіңіз."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" үшін SIM PIN кодын енгізіңіз."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Құрылғыны мобильдік байланыс қызметінсіз пайдалану үшін eSIM картасын өшіріңіз."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"PIN кодын енгізіңіз"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Кілтсөзді енгізіңіз"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM картасы өшірілді. Жалғастыру үшін PUK кодын енгізіңіз. Толығырақ ақпаратты оператордан алыңыз."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" SIM картасы қазір өшірулі. Жалғастыру үшін PUK кодын енгізіңіз. Мәліметтер алу үшін операторға хабарласыңыз."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Қажетті PIN кодын енгізіңіз"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM картасының құлпын ашуда…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4-8 саннан тұратын PIN кодын енгізіңіз."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK коды 8 не одан көп саннан тұруы қажет."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Дұрыс PUK кодын қайта енгізіңіз. Әрекетті қайталай берсеңіз, SIM картасы өшіріледі."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Тым көп өрнек енгізу әрекеті жасалды"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN коды <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін әркетті қайталаңыз."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Құпия сөз <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Құлыпты ашу өрнегі <xliff:g id="NUMBER_0">%1$d</xliff:g> рет қате енгізілді. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундтан кейін әрекетті қайталаңыз."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN кодымен құлпы ашылмады!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK кодымен құлпы ашылмады!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Код қабылданды!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Қызмет көрсетілмейді."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Енгізу әдісін ауыстыру"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Ұшақ режимі"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Құрылғы қайта іске қосылғаннан кейін, өрнекті енгізу қажет"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Қауіпсіздікті күшейту үшін өрнекті енгізу қажет"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Қауіпсіздікті күшейту үшін PIN кодын енгізу қажет"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Қауіпсіздікті күшейту үшін құпия сөзді енгізу қажет"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Профильдерді ауыстырғанда өрнекті енгізу қажет"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Профильдерді ауыстырғанда PIN кодын енгізу қажет"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Профильдерді ауыстырғанда құпия сөзді енгізу қажет"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Құрылғыны әкімші құлыптаған"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Құрылғы қолмен құлыпталды"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Құрылғы құлпы <xliff:g id="NUMBER_1">%d</xliff:g> сағаттан бері ашылмаған. Өрнекті растаңыз.</item>
-      <item quantity="one">Құрылғы құлпы <xliff:g id="NUMBER_0">%d</xliff:g> сағаттан бері ашылмаған. Өрнекті растаңыз.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Құрылғы құлпы <xliff:g id="NUMBER_1">%d</xliff:g> сағаттан бері ашылмаған. PIN кодын растаңыз.</item>
-      <item quantity="one">Құрылғы құлпы <xliff:g id="NUMBER_0">%d</xliff:g> сағаттан бері ашылмаған. PIN кодын растаңыз.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Құрылғы құлпы <xliff:g id="NUMBER_1">%d</xliff:g> сағаттан бері ашылмаған. Құпия сөзді растаңыз.</item>
-      <item quantity="one">Құрылғы құлпы <xliff:g id="NUMBER_0">%d</xliff:g> сағаттан бері ашылмаған. Құпия сөзді растаңыз.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Танылмады"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Танылмады"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-km/strings.xml b/packages/SystemUI/res-keyguard/values-km/strings.xml
index eca4957..388d4fc 100644
--- a/packages/SystemUI/res-keyguard/values-km/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-km/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"វាយ​បញ្ចូល​កូដ PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"វាយ​បញ្ចូលកូដ PIN ថ្មី​ និងកូដ PUK របស់​ស៊ីម"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"កូដ PUK របស់​ស៊ីម"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"កូដ PIN របស់​ស៊ីម​ថ្មី"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"ចុច​ដើម្បី​បញ្ចូល​ពាក្យ​សម្ងាត់"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"វាយ​បញ្ចូល​ពាក្យ​សម្ងាត់​ ដើម្បី​ដោះ​សោ"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"វាយ​បញ្ចូល​កូដ PIN ដើម្បី​ដោះ​សោ"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"បញ្ចូល​កូដ PIN របស់​អ្នក"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"បញ្ចូល​លំនាំ​របស់​អ្នក"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"បញ្ចូល​ពាក្យ​សម្ងាត់​របស់អ្នក"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"កូដ PIN មិន​ត្រឹមត្រូវ​ទេ។"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"បណ្ណមិនត្រឹមត្រូវទេ។"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"បាន​សាក​ថ្មពេញ"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុងសាកថ្ម​ឥតខ្សែ"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយ៉ាង​ឆាប់រហ័ស"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • កំពុង​សាកថ្មយឺត"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • បានដាក់កំហិតលើ​ការសាកថ្មជា​បណ្ដោះអាសន្ន"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"សូមសាក​ថ្ម​របស់​អ្នក។"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ចុចម៉ឺនុយ ​ដើម្បី​ដោះ​សោ។"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"បណ្ដាញ​ជាប់​សោ"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"គ្មាន​ស៊ីម​កាត​ទេ"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"ពាក្យសម្ងាត់​ឧបករណ៍"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"ប្រអប់​បំពេញ​កូដ PIN របស់​ស៊ីម"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"ប្រអប់​បំពេញ​កូដ PUK របស់​ស៊ីម"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"បាន​កំណត់ម៉ោង​រោទិ៍​បន្ទាប់​នៅថ្ងៃ <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"លុប"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"បិទ eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"មិនអាច​បិទ eSIM បាន​ទេ"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"មិនអាច​បិទ eSIM បានទេ ដោយសារ​មាន​បញ្ហា។"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"ភ្លេច​​លំនាំ"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"លំនាំមិនត្រឹមត្រូវ"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"ពាក្យសម្ងាត់មិនត្រឹមត្រូវ"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"កូដ PIN មិន​ត្រឹមត្រូវ​ទេ"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">ព្យាយាមម្តងទៀតក្នុងរយៈពេល <xliff:g id="NUMBER">%d</xliff:g> វិនាទី។</item>
       <item quantity="one">ព្យាយាមម្តងទៀតក្នុងរយៈពេល 1 វិនាទី។</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"គូរ​លំនាំ​របស់​អ្នក"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"បញ្ចូល​កូដ PIN របស់​ស៊ីម។"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"បញ្ចូល​កូដ PIN របស់​ស៊ីម​សម្រាប់ \"<xliff:g id="CARRIER">%1$s</xliff:g>\"។"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> បិទ eSIM ដើម្បី​ប្រើ​ឧបករណ៍​ដោយ​គ្មាន​សេវាកម្ម​ទូរសព្ទ​ចល័ត។"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"បញ្ចូល​កូដ PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"បញ្ចូល​ពាក្យ​សម្ងាត់"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"ឥឡូវ​នេះ​ ស៊ីម​ត្រូវ​បាន​បិទ​ដំណើរការ​ហើយ។ បញ្ចូល​កូដ PUK ដើម្បី​បន្ត។ សូម​ទាក់ទង​ទៅក្រុមហ៊ុន​បម្រើ​សេវា​ទូរសព្ទ​របស់​អ្នក ដើម្បី​ទទួល​បាន​ព័ត៌មាន​លម្អិត។"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"ឥឡូវ​នេះ​ ស៊ីម \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ត្រូវ​បាន​បិទ​ដំណើរការហើយ។ បញ្ចូល​កូដ PUK ដើម្បី​បន្ត។ សូម​ទាក់ទង​ទៅក្រុមហ៊ុន​បម្រើ​សេវា​ទូរសព្ទ​របស់​អ្នក ដើម្បី​ទទួល​បាន​ព័ត៌មាន​លម្អិត។"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"បញ្ចូល​កូដ PIN ដែល​ចង់​បាន"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"កំពុង​ដោះ​សោ​ស៊ីមកាត..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"វាយ​បញ្ចូល​កូដ PIN ​ចន្លោះពី 4 ទៅ 8 ខ្ទង់"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"កូដ PUK គួរ​តែ​មាន​លេខ 8 ខ្ទង់ ឬ​ច្រើន​ជាង​នេះ។"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"សូម​បញ្ចូល​កូដ PUK ម្ដង​ទៀត។ ការ​ព្យាយាម​ដដែល​ច្រើន​ដង​នឹង​បិទ​ដំណើរការ​ស៊ីម​នេះ​ជា​អចិន្ត្រៃយ៍។"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"ការព្យាយាម​បញ្ចូល​លំនាំ​ច្រើន​ដង​ពេកហើយ"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"អ្នក​បាន​វាយ​បញ្ចូល​កូដ PIN របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ \n\nសូម​ព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_1">%2$d</xliff:g> វិនាទី​ទៀត។"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"អ្នក​បាន​វាយ​បញ្ចូល​ពាក្យ​សម្ងាត់​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ \n\nសូម​ព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_1">%2$d</xliff:g> វិនាទី​ទៀត។"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"អ្នក​បាន​គូរ​លំនាំ​ដោះ​សោ​របស់​អ្នក​មិន​ត្រឹមត្រូវ​ចំនួន <xliff:g id="NUMBER_0">%1$d</xliff:g> ដង​ហើយ។ \n\nសូមព្យាយាម​ម្ដង​ទៀត​ក្នុង​រយៈ​ពេល <xliff:g id="NUMBER_1">%2$d</xliff:g> វិនាទី​ទៀត។"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"មិន​អាច​ដោះ​សោ​ដោយ​ប្រើកូដ​ PIN របស់​ស៊ីម​បានទេ!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"មិន​អាច​ដោះ​សោ​ដោយ​ប្រើកូដ​ PUK របស់​ស៊ីម​បានទេ!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"កូដត្រូវ​បានទទួល​យក!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"គ្មាន​សេវា​ទេ។"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ប្ដូរ​វិធី​បញ្ចូល"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"​ពេល​ជិះ​យន្តហោះ"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"តម្រូវឲ្យប្រើលំនាំ បន្ទាប់ពីឧបករណ៍ចាប់ផ្តើមឡើងវិញ"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"តម្រូវឲ្យប្រើលំនាំ ដើម្បីទទួលបានសវុត្ថិភាពបន្ថែម"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"តម្រូវឲ្យបញ្ចូលកូដ PIN ដើម្បីទទួលបានសុវត្ថិភាពបន្ថែម"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"តម្រូវឲ្យបញ្ចូលពាក្យសម្ងាត់ ដើម្បីទទួលបានសុវត្ថិភាពបន្ថែម"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"តម្រូវ​ឲ្យ​ប្រើ​លំនាំ​ នៅ​ពេល​ដែល​អ្នក​ប្តូរកម្រង​ព័ត៌មាន"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"តម្រូវ​ឲ្យ​បញ្ចូល​កូដ PIN នៅ​ពេល​ដែល​អ្នក​ប្តូរ​កម្រង​ព័ត៌មាន"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"តម្រូវ​ឲ្យ​បញ្ចូល​ពាក្យសម្ងាត់​ នៅ​ពេល​ដែល​អ្នក​ប្តូរ​កម្រង​ព័ត៌មាន"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ឧបករណ៍​ត្រូវបាន​ចាក់សោ​ដោយអ្នក​គ្រប់គ្រង"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ឧបករណ៍ត្រូវបានចាក់សោដោយអ្នកប្រើផ្ទាល់"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">ឧបករណ៍​បាន​ជាប់​សោ​អស់រយៈ​ពេល <xliff:g id="NUMBER_1">%d</xliff:g> ម៉ោង​ហើយ។ សូម​បញ្ជាក់​លំនាំ។</item>
-      <item quantity="one">ឧបករណ៍​បាន​ជាប់​សោ​អស់រយៈ​ពេល <xliff:g id="NUMBER_0">%d</xliff:g> ម៉ោង​ហើយ។ សូម​បញ្ជាក់​លំនាំ។</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">ឧបករណ៍​បាន​ជាប់​សោ​អស់រយៈ​ពេល <xliff:g id="NUMBER_1">%d</xliff:g> ម៉ោង​ហើយ។ សូម​បញ្ជាក់​កូដ PIN ។</item>
-      <item quantity="one">ឧបករណ៍​បាន​ជាប់​សោ​អស់រយៈ​ពេល <xliff:g id="NUMBER_0">%d</xliff:g> ម៉ោង​ហើយ។ សូម​បញ្ជាក់​កូដ PIN ។</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">ឧបករណ៍​បាន​ជាប់​សោ​អស់រយៈ​ពេល <xliff:g id="NUMBER_1">%d</xliff:g> ម៉ោង​ហើយ។ សូម​បញ្ជាក់​ពាក្យ​សម្ងាត់។</item>
-      <item quantity="one">ឧបករណ៍​បាន​ជាប់​សោ​អស់រយៈ​ពេល <xliff:g id="NUMBER_0">%d</xliff:g> ម៉ោង​ហើយ។ សូម​បញ្ជាក់​ពាក្យ​សម្ងាត់។</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"មិនអាចសម្គាល់បានទេ"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"មិនអាចសម្គាល់បានទេ"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-kn/strings.xml b/packages/SystemUI/res-keyguard/values-kn/strings.xml
index 5cbe02e..9279fad 100644
--- a/packages/SystemUI/res-keyguard/values-kn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-kn/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"ಕೀಗಾರ್ಡ್"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"ಪಿನ್‌ ಕೋಡ್‌ ಟೈಪ್‌ ಮಾಡಿ"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"ಸಿಮ್‌ PUK ಮತ್ತು ಹೊಸ ಪಿನ್‌ ಕೋಡ್ ಟೈಪ್ ಮಾಡಿ"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"ಸಿಮ್‌ PUK ಕೋಡ್"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"ಹೊಸ ಸಿಮ್‌ ಪಿನ್‌ ಕೋಡ್"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"ಪಾಸ್‌ವರ್ಡ್‌ ಟೈಪ್ ಮಾಡಲು ಸ್ಪರ್ಶಿಸಿ"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"ಅನ್‌ಲಾಕ್‌ ಮಾಡಲು ಪಾಸ್‌ವರ್ಡ್‌ ಟೈಪ್‌ ಮಾಡಿ"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"ಅನ್‌ಲಾಕ್‌ ಮಾಡಲು ಪಿನ್‌ ಟೈಪ್‌ ಮಾಡಿ"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"ನಿಮ್ಮ ಪಿನ್ ನಮೂದಿಸಿ"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"ನಿಮ್ಮ ಪ್ಯಾಟರ್ನ್ ನಮೂದಿಸಿ"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"ನಿಮ್ಮ ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"ತಪ್ಪಾದ ಪಿನ್‌ ಕೋಡ್."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ಅಮಾನ್ಯ ಕಾರ್ಡ್."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"ಚಾರ್ಜ್ ಆಗಿದೆ"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೈರ್‌ಲೆಸ್ ಆಗಿ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ವೇಗವಾಗಿ ಚಾರ್ಜ್‌ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ನಿಧಾನವಾಗಿ ಚಾರ್ಜ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ಸೀಮಿತಗೊಳಿಸಲಾಗಿದೆ"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"ನಿಮ್ಮ ಚಾರ್ಜರ್ ಸಂಪರ್ಕಗೊಳಿಸಿ."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಮೆನು ಒತ್ತಿರಿ."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ನೆಟ್‌ವರ್ಕ್ ಲಾಕ್ ಆಗಿದೆ"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ಸಿಮ್‌ ಕಾರ್ಡ್ ಇಲ್ಲ"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"ಸಾಧನದ ಪಾಸ್‌ವರ್ಡ್‌"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"ಸಿಮ್ ಪಿನ್ ಪ್ರದೇಶ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"ಸಿಮ್ PUK ಪ್ರದೇಶ"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"<xliff:g id="ALARM">%1$s</xliff:g> ಗಂಟೆಗೆ ಮುಂದಿನ ಅಲಾರಮ್ ಹೊಂದಿಸಲಾಗಿದೆ"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"ಅಳಿಸಿ"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"ದೋಷದ ಕಾರಣದಿಂದಾಗಿ eSIM ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"ನಮೂದಿಸಿ"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"ಪ್ಯಾಟರ್ನ್ ಮರೆತಿದ್ದೀರಿ"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"ಪ್ಯಾಟರ್ನ್ ತಪ್ಪಾಗಿದೆ"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"ತಪ್ಪು ಪಾಸ್‌ವರ್ಡ್"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"ಪಿನ್‌ ತಪ್ಪಾಗಿದೆ"</string>
@@ -68,12 +56,9 @@
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</item>
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"ನಿಮ್ಮ ಪ್ಯಾಟರ್ನ್ ಚಿತ್ರಿಸಿ"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"ಸಿಮ್‌ ಪಿನ್‌ ನಮೂದಿಸಿ."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" ಗಾಗಿ ಸಿಮ್ ಪಿನ್ ನಮೂದಿಸಿ."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> ಮೊಬೈಲ್ ಸೇವೆ ಇಲ್ಲದೆ ಸಾಧನವನ್ನು ಬಳಸಲು eSIM ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"ಪಿನ್‌ ನಮೂದಿಸಿ"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"ಪಾಸ್‌ವರ್ಡ್ ನಮೂದಿಸಿ"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"ಈಗ ಸಿಮ್‌ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ. ಮುಂದುವರೆಯಲು PUK ಕೋಡ್ ನಮೂದಿಸಿ. ವಿವರಗಳಿಗಾಗಿ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"ಈಗ \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ಸಿಮ್ ನಿಷ್ಕ್ರಿಯಗೊಂಡಿದೆ. ಮುಂದುವರೆಯಲು PUK ಕೋಡ್ ನಮೂದಿಸಿ. ಮಾಹಿತಿಗಾಗಿ ವಾಹಕವನ್ನು ಸಂಪರ್ಕಿಸಿ."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"ಬಯಸಿರುವ ಪಿನ್‌ ಕೋಡ್ ನಮೂದಿಸಿ"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"ಸಿಮ್‌ ಕಾರ್ಡ್ ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗುತ್ತಿದೆ…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 ರಿಂದ 8 ಸಂಖ್ಯೆಗಳಿರುವ ಪಿನ್‌ ಟೈಪ್ ಮಾಡಿ."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK ಕೋಡ್ 8 ಅಥವಾ ಹೆಚ್ಚು ಸಂಖ್ಯೆಗಳನ್ನು ಹೊಂದಿರಬೇಕು."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"ಸರಿಯಾದ PUK ಕೋಡ್ ಮರು-ನಮೂದಿಸಿ. ಸತತ ಪ್ರಯತ್ನಗಳು ಸಿಮ್‌ ಅನ್ನು ಶಾಶ್ವತವಾಗಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"ಪ್ಯಾಟರ್ನ್ ಪ್ರಯತ್ನಗಳ ಮಿತಿ ಮುಗಿದಿದೆ"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ನಿಮ್ಮ ಪಿನ್‌ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಟೈಪ್ ಮಾಡಿದ್ದೀರಿ. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ನಿಮ್ಮ ಪಾಸ್‍‍ವರ್ಡ್ ಅನ್ನು ನೀವು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ನಮೂದಿಸಿದ್ದೀರಿ. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ನಿಮ್ಮ ಅನ್‍‍ಲಾಕ್ ಪ್ಯಾಟರ್ನ್‌ ಅನ್ನು <xliff:g id="NUMBER_0">%1$d</xliff:g> ಬಾರಿ ತಪ್ಪಾಗಿ ಎಳೆದಿದ್ದೀರಿ. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ಸೆಕೆಂಡುಗಳಲ್ಲಿ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"ಸಿಮ್‌ ಪಿನ್‌ ಕಾರ್ಯಾಚರಣೆ ವಿಫಲಗೊಂಡಿದೆ!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"ಸಿಮ್‌ PUK ಕಾರ್ಯಾಚರಣೆ ವಿಫಲಗೊಂಡಿದೆ!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"ಕೋಡ್ ಅಂಗೀಕೃತವಾಗಿದೆ!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"ಸೇವೆ ಇಲ್ಲ."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ಇನ್‌ಪುಟ್‌‌ ವಿಧಾನ ಬದಲಿಸಿ"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ಸಾಧನ ಮರುಪ್ರಾರಂಭಗೊಂಡ ನಂತರ ಪ್ಯಾಟರ್ನ್ ಅಗತ್ಯವಿರುತ್ತದೆ"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ಹೆಚ್ಚುವರಿ ಭದ್ರತೆಗೆ ಪ್ಯಾಟರ್ನ್ ಅಗತ್ಯವಿದೆ"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ಹೆಚ್ಚುವರಿ ಭದ್ರತೆಗೆ ಪಿನ್ ಅಗತ್ಯವಿದೆ"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ಹೆಚ್ಚುವರಿ ಭದ್ರತೆಗಾಗಿ ಪಾಸ್‌ವರ್ಡ್ ಅಗತ್ಯವಿದೆ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"ನೀವು ಪ್ರೊಫೈಲ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಿದಾಗ ಪ್ಯಾಟರ್ನ್ ಅಗತ್ಯವಿರುತ್ತದೆ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"ನೀವು ಪ್ರೊಫೈಲ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಿದಾಗ ಪಿನ್ ಅಗತ್ಯವಿರುತ್ತದೆ"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"ನೀವು ಪ್ರೊಫೈಲ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಿದಾಗ ಪಾಸ್‌ವರ್ಡ್‌ ಅಗತ್ಯವಿರುತ್ತದೆ"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ನಿರ್ವಾಹಕರು ಸಾಧನವನ್ನು ಲಾಕ್ ಮಾಡಿದ್ದಾರೆ"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ಸಾಧನವನ್ನು ಹಸ್ತಚಾಲಿತವಾಗಿ ಲಾಕ್‌ ಮಾಡಲಾಗಿದೆ"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">ಸಾಧನವನ್ನು <xliff:g id="NUMBER_1">%d</xliff:g> ಗಂಟೆಗಳವರೆಗೆ ಅನ್‌ಲಾಕ್‌ ಮಾಡಿರಲಿಲ್ಲ. ಪ್ಯಾಟರ್ನ್‌ ಖಚಿತಪಡಿಸಿ.</item>
-      <item quantity="other">ಸಾಧನವನ್ನು <xliff:g id="NUMBER_1">%d</xliff:g> ಗಂಟೆಗಳವರೆಗೆ ಅನ್‌ಲಾಕ್‌ ಮಾಡಿರಲಿಲ್ಲ. ಪ್ಯಾಟರ್ನ್‌ ಖಚಿತಪಡಿಸಿ.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">ಸಾಧನವನ್ನು <xliff:g id="NUMBER_1">%d</xliff:g> ಗಂಟೆಗಳವರೆಗೆ ಅನ್‌ಲಾಕ್‌ ಮಾಡಿರಲಿಲ್ಲ. ಪಿನ್ ದೃಢೀಕರಿಸಿ.</item>
-      <item quantity="other">ಸಾಧನವನ್ನು <xliff:g id="NUMBER_1">%d</xliff:g> ಗಂಟೆಗಳವರೆಗೆ ಅನ್‌ಲಾಕ್‌ ಮಾಡಿರಲಿಲ್ಲ. ಪಿನ್ ದೃಢೀಕರಿಸಿ.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">ಸಾಧನವನ್ನು <xliff:g id="NUMBER_1">%d</xliff:g> ಗಂಟೆಗಳವರೆಗೆ ಅನ್‌ಲಾಕ್‌ ಮಾಡಿರಲಿಲ್ಲ. ಪಾಸ್‌ವರ್ಡ್‌ ಖಚಿತಪಡಿಸಿ.</item>
-      <item quantity="other">ಸಾಧನವನ್ನು <xliff:g id="NUMBER_1">%d</xliff:g> ಗಂಟೆಗಳವರೆಗೆ ಅನ್‌ಲಾಕ್‌ ಮಾಡಿರಲಿಲ್ಲ. ಪಾಸ್‌ವರ್ಡ್‌ ಖಚಿತಪಡಿಸಿ.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"ಗುರುತಿಸಲಾಗಿಲ್ಲ"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ko/strings.xml b/packages/SystemUI/res-keyguard/values-ko/strings.xml
index 4afde28..761ccfa 100644
--- a/packages/SystemUI/res-keyguard/values-ko/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ko/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"키가드"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"PIN 코드 입력"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM PUK 및 새 PIN 코드 입력"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK 코드"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"새 SIM PIN 코드"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"터치하여 비밀번호 입력"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"잠금 해제하려면 비밀번호 입력"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"잠금 해제하려면 PIN 입력"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"PIN을 입력해 주세요."</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"패턴 입력"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"비밀번호 입력"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"잘못된 PIN 코드입니다."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"유효하지 않은 카드"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"충전됨"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 무선 충전 중"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 고속 충전 중"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 저속 충전 중"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 충전이 일시적으로 제한됨"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"충전기를 연결하세요."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"잠금 해제하려면 메뉴를 누르세요."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"네트워크 잠김"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM 카드 없음"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"기기 비밀번호"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN 영역"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK 영역"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"<xliff:g id="ALARM">%1$s</xliff:g>에 다음 알람이 설정됨"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"삭제"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM 사용 중지"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM을 사용 중지할 수 없음"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"오류로 인해 eSIM을 사용 중지할 수 없습니다."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter 키"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"패턴을 잊음"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"잘못된 패턴"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"잘못된 비밀번호"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN 오류"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g>초 후에 다시 시도하세요.</item>
       <item quantity="one">1초 후에 다시 시도하세요.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"패턴 그리기"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM PIN을 입력하세요."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\'<xliff:g id="CARRIER">%1$s</xliff:g>\'의 SIM PIN을 입력하세요."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> 모바일 서비스 없이 기기를 사용하려면 eSIM을 사용 중지하세요."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"PIN 입력"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"비밀번호 입력"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM이 사용 중지되었습니다. 계속하려면 PUK 코드를 입력하세요. 자세한 내용은 이동통신사에 문의하시기 바랍니다."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \'<xliff:g id="CARRIER">%1$s</xliff:g>\'이(가) 사용 중지되었습니다. 계속하려면 PUK 코드를 입력하세요. 자세한 내용은 이동통신사에 문의하시기 바랍니다."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"원하는 PIN 코드 입력"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM 카드 잠금 해제 중..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4~8자리 숫자로 된 PIN을 입력하세요."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK 코드는 8자리 이상의 숫자여야 합니다."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"올바른 PUK 코드를 다시 입력하세요. 입력을 반복해서 시도하면 SIM이 영구적으로 사용 중지됩니다."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"패턴 그리기를 너무 많이 시도함"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN을 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 잘못 입력했습니다. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>초 후에 다시 시도하세요."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"비밀번호를 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 잘못 입력했습니다. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>초 후에 다시 시도하세요."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%1$d</xliff:g>번 잘못 그렸습니다. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g>초 후에 다시 시도하세요."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN 작업이 실패했습니다."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK 작업이 실패했습니다."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"올바른 코드입니다."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"서비스 불가"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"입력 방법 전환"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"비행기 모드"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"기기가 다시 시작되면 패턴이 필요합니다."</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"보안 강화를 위해 패턴이 필요합니다."</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"보안 강화를 위해 PIN이 필요합니다."</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"보안 강화를 위해 비밀번호가 필요합니다."</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"프로필을 전환하려면 패턴이 필요합니다."</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"프로필을 전환하려면 PIN이 필요합니다."</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"프로필을 전환하려면 비밀번호가 필요합니다."</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"관리자가 기기를 잠갔습니다."</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"기기가 수동으로 잠금 설정되었습니다."</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">기기가 <xliff:g id="NUMBER_1">%d</xliff:g>시간 동안 잠금 해제되지 않았습니다. 패턴을 입력하세요.</item>
-      <item quantity="one">기기가 <xliff:g id="NUMBER_0">%d</xliff:g>시간 동안 잠금 해제되지 않았습니다. 패턴을 입력하세요.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">기기가 <xliff:g id="NUMBER_1">%d</xliff:g>시간 동안 잠금 해제되지 않았습니다. PIN을 입력하세요.</item>
-      <item quantity="one">기기가 <xliff:g id="NUMBER_0">%d</xliff:g>시간 동안 잠금 해제되지 않았습니다. PIN을 입력하세요.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">기기가 <xliff:g id="NUMBER_1">%d</xliff:g>시간 동안 잠금 해제되지 않았습니다. 비밀번호를 입력하세요.</item>
-      <item quantity="one">기기가 <xliff:g id="NUMBER_0">%d</xliff:g>시간 동안 잠금 해제되지 않았습니다. 비밀번호를 입력하세요.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"인식할 수 없음"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"인식할 수 없음"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ky/strings.xml b/packages/SystemUI/res-keyguard/values-ky/strings.xml
index ced155a..216c978 100644
--- a/packages/SystemUI/res-keyguard/values-ky/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ky/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Баскычтопту бөгөттөгүч"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"PIN-кодду териңиз"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM-картанын PUK-кодун, анан жаңы PIN-кодун териңиз"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM-картанын PUK-коду"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"SIM-картанын жаңы PIN-коду"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Сырсөздү терүү үчүн тийип коюңуз"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Кулпуну ачуу үчүн сырсөздү териңиз"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Кулпуну ачуу үчүн PIN-кодду териңиз"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"PIN кодуңузду киргизиңиз"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Графикалык ачкычты киргизиңиз"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Сырсөзүңүздү киргизиңиз"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN-код туура эмес."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"SIM-карта жараксыз."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Кубатталды"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зымсыз кубатталууда"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Тез кубатталууда"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Жай кубатталууда"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Кубаттоо убактылуу чектелген"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Кубаттагычка туташтырыңыз."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Кулпуну ачуу үчүн Менюну басыңыз."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Тармак кулпуланган"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM карта жок"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Түзмөктүн сырсөзү"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM-картанын PIN-кодунун аймагы"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM-картанын PUK-кодунун аймагы"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Кийинки ойготкуч саат <xliff:g id="ALARM">%1$s</xliff:g> коюлган"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Жок кылуу"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM-картаны өчүрүү"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM-картаны өчүрүүгө болбойт"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Катадан улам eSIM-картаны өчүрүүгө болбойт."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Киргизүү"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Графикалык ачкычты унутуп калдым"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Графикалык ачкыч туура эмес"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Сырсөз туура эмес"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN-код туура эмес"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> секунддан кийин кайталаңыз.</item>
       <item quantity="one">1 секунддан кийин кайталаңыз.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Графикалык ачкычты тартыңыз"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM-картанын PIN-кодун киргизиңиз."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" SIM-картасынын PIN-кодун киргизиңиз."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Түзмөктү мобилдик кызматсыз колдонуу үчүн eSIM-картаны өчүрүңүз."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"PIN-кодду киргизиңиз"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Сырсөздү киргизиңиз"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM-карта азыр жарактан чыкты. Улантуу үчүн PUK-кодду киргизиңиз. Анын чоо-жайын билүү үчүн байланыш операторуна кайрылыңыз."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Эми SIM-картанын \"<xliff:g id="CARRIER">%1$s</xliff:g>\" байланыш оператору өчүрүлдү. Улантуу үчүн PUK-кодду киргизиңиз. Анын чоо-жайын билүү үчүн байланыш операторуна кайрылыңыз."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Сиз каалаган PIN-кодду териңиз"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM-карта бөгөттөн чыгарылууда…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4–8 сандан турган PIN-кодду териңиз."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-код 8 же андан көп сандан турушу керек."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"PUK-кодду кайрадан туура киргизиңиз. Кайталанган аракеттер SIM картаны биротоло жараксыз кылат."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Өтө көп графикалык ачкычты тартуу аракети болду"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN-кодуңузду <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Сырсөзүңүздү <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тердиңиз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Түзмөктү ачуучу графикалык  ачкычты <xliff:g id="NUMBER_0">%1$d</xliff:g> жолу туура эмес тарттыңыз. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секунддан кийин дагы аракет кылып көрүңүз."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM-картанын PIN-кодун ачуу кыйрады!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM-картанын PUK-кодун ачуу кыйрады!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Код кабыл алынды!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Интернет жок."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Киргизүү ыкмасын өзгөртүү"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Учак режими"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Түзмөк кайра күйгүзүлгөндөн кийин графикалык ачкычты тартуу талап кылынат"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Коопсуздукту бекемдөө үчүн графикалык ачкыч талап кылынат"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Коопсуздукту бекемдөө үчүн PIN-код талап кылынат"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Коопсуздукту бекемдөө үчүн сырсөз талап кылынат"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Профилдерди которуштурганда графикалык ачкыч талап кылынат"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Профилдерди которуштурганда PIN-код талап кылынат"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Профилдерди которуштурганда сырсөз талап кылынат"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Түзмөктү администратор кулпулап койгон"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Түзмөк кол менен кулпуланды"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Түзмөктүн кулпусу <xliff:g id="NUMBER_1">%d</xliff:g> саат бою ачылган жок. Графикалык ачкычты ырастаңыз.</item>
-      <item quantity="one">Түзмөктүн кулпусу <xliff:g id="NUMBER_0">%d</xliff:g> саат бою ачылган жок. Графикалык ачкычты ырастаңыз.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Түзмөктүн кулпусу <xliff:g id="NUMBER_1">%d</xliff:g> саат бою ачылган жок. PIN-кодду ырастаңыз.</item>
-      <item quantity="one">Түзмөктүн кулпусу <xliff:g id="NUMBER_0">%d</xliff:g> саат бою ачылган жок. PIN-кодду ырастаңыз.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Түзмөктүн кулпусу <xliff:g id="NUMBER_1">%d</xliff:g> саат бою ачылган жок. Сырсөздү ырастаңыз.</item>
-      <item quantity="one">Түзмөктүн кулпусу <xliff:g id="NUMBER_0">%d</xliff:g> саат бою ачылган жок. Сырсөздү ырастаңыз.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Таанылган жок"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Таанылган жок"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-lo/strings.xml b/packages/SystemUI/res-keyguard/values-lo/strings.xml
index b6fd676..a9dd139 100644
--- a/packages/SystemUI/res-keyguard/values-lo/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lo/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"ພິມລະຫັດ PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"ປະເພດ PUK ຂອງ SIM ແລະລະຫັດ PIN ໃໝ່"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"ລະຫັດ PUK ຂອງ SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"ລະຫັດ PIN ໃໝ່ຂອງ SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"ແຕະເພື່ອພິມລະຫັດຜ່ານ"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"ພິມລະຫັດເພື່ອປົດລັອກ"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"ພິມລະຫັດ PIN ເພື່ອປົດລັອກ"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"ໃສ່ລະຫັດ PIN ຂອງທ່ານ"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"ໃສ່ຮູບແບບປົດລັອກຂອງທ່ານ"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"ປ້ອນລະຫັດຜ່ານຂອງທ່ານ"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"ລະຫັດ PIN ບໍ່ຖືກຕ້ອງ."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ບັດບໍ່ຖືກຕ້ອງ."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"ສາກເຕັມແລ້ວ."</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳ​ລັງ​ສາກ​ໄຟໄຮ້​ສາຍ"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບດ່ວນ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ກຳລັງສາກແບບຊ້າ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ຈຳກັດການສາກໄຟຊົ່ວຄາວແລ້ວ"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"ເຊື່ອມຕໍ່ສາຍສາກຂອງທ່ານ."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ກົດ \"ເມນູ\" ເພື່ອປົດລັອກ."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ເຄືອຂ່າຍຖືກລັອກ"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ບໍ່ມີຊິມກາດ"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"ລະຫັດຜ່ານອຸປະກອນ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"ພື້ນທີ່ PIN ຂອງ SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"ພື້ນທີ່ PUK ຂອງ SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"ໂມງປຸກຕໍ່ໄປຖືກຕັ້ງໄວ້ເວລາ <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"ລຶບ"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"ປິດການໃຊ້ eSIM ແລ້ວ"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"ບໍ່ສາມາດປິດການເຮັດວຽກຂອງ eSIM ໄດ້"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"ບໍ່ສາມາດປິດການນຳໃຊ້ eSIM ໄດ້ເນື່ອງຈາກມີຂໍ້ຜິດພາດ."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"ປ້ອນເຂົ້າ"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"ລືມຮູບແບບປົດລັອກ?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"ຮູບແບບບໍ່ຖືກຕ້ອງ"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"ລະຫັດຜ່ານບໍ່ຖືກຕ້ອງ"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"ລະຫັດ PIN ບໍ່ຖືກຕ້ອງ"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">ລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER">%d</xliff:g> ວິນາທີ.</item>
       <item quantity="one">ລອງໃໝ່ໃນອີກ 1 ວິນາທີ.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"ແຕ້ມຮູບແບບປົດລັອກຂອງທ່ານ"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"ໃສ່ລະຫັດ PIN ຂອງຊິມ."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"ໃສ່ລະຫັດ PIN ຂອງຊິມສຳລັບ \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> ປິດການນຳໃຊ້ eSIM ເພື່ອໃຊ້ອຸປະກອນໂດຍບໍ່ຕ້ອງເຊື່ອມຕໍ່ເຄືອຂ່າຍ."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"ໃສ່ລະຫັດ PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"ໃສ່ລະຫັດຜ່ານ"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"ຊິມຖືກປິດການນຳໃຊ້ແລ້ວ. ປ້ອນລະຫັດ PUK ເພື່ອດຳເນີນການຕໍ່. ຕິດຕໍ່ຜູ່ໃຫ້ບໍລິການສຳລັບລາຍລະອຽດ."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"ດຽວນີ້ \"<xliff:g id="CARRIER">%1$s</xliff:g>\" SIM ປິດນຳໃຊ້. ປ້ອນລະຫັດ PUK ເພື່ອສືບຕໍ່. ຕິດຕໍ່ບໍລິສັດໃຫ້ບໍລິການ ເພື່ອຂໍລາຍລະອຽດ."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"ໃສ່ລະຫັດ PIN ທີ່ຕ້ອງການ."</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"ປົດລັອກ SIM card..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"ພິມລະຫັດ PIN ທີ່ມີ 4 ຫາ 8 ໂຕເລກ."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"ລະຫັດ PUK ຄວນມີຢ່າງໜ້ອຍ 8 ໂຕເລກ."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"ປ້ອນລະຫັດ PUK ທີ່ຖືກຕ້ອງຄືນໃໝ່. ການພະຍາຍາມໃສ່ຫຼາຍເທື່ອຈະເຮັດໃຫ້ຊິມກາດໃຊ້ບໍ່ໄດ້ຖາວອນ."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"ແຕ້ມຮູບແບບປົດລັອກຫຼາຍເກີນໄປ"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ທ່ານພິມລະຫັດ PIN ຂອງທ່ານຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. \n\nກະລຸນາລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ວິນາທີ."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ທ່ານພິມລະຫັດຜ່ານຜິດ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. \n\nໃຫ້ລອງໃໝ່ອີກຄັ້ງໃນອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ວິນາທີ."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ທ່ານແຕ້ມຮູບແບບປົດລັອກບໍ່ຖືກ <xliff:g id="NUMBER_0">%1$d</xliff:g> ເທື່ອແລ້ວ. \n\nລອງໃໝ່ໃນອີກ <xliff:g id="NUMBER_1">%2$d</xliff:g> ວິນາທີ."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"PIN ຂອງ SIM ເຮັດວຽກລົ້ມເຫຼວ!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"PUK ຂອງ SIM ເຮັດວຽກລົ້ມເຫຼວ!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"ລະຫັດຖືກຕອບຮັບແລ້ວ!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"ບໍ່ມີບໍລິການ"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ສະລັບຮູບແບບການປ້ອນຂໍ້ມູນ"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"ໂໝດໃນຍົນ"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ຈຳເປັນຕ້ອງມີແບບຮູບປົດລັອກຫຼັງຈາກອຸປະກອນເລີ່ມລະບົບໃໝ່"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ຈຳເປັນຕ້ອງມີແບບຮູບເພື່ອຄວາມປອດໄພເພີ່ມເຕີມ"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ຈຳເປັນຕ້ອງມີ PIN ເພື່ອຄວາມປອດໄພເພີ່ມເຕີມ"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ຈຳເປັນຕ້ອງມີລະຫັດຜ່ານເພື່ອຄວາມປອດໄພເພີ່ມເຕີມ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"ຈຳເປັນຕ້ອງມີແບບຮູບ ເມື່ອທ່ານປ່ຽນໂປຣໄຟລ໌"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"ຈຳເປັນຕ້ອງມີ PIN ເມື່ອທ່ານປ່ຽນໂປຣໄຟລ໌"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"ຈຳເປັນຕ້ອງມີລະຫັດຜ່ານ ເມື່ອທ່ານປ່ຽນໂປຣໄຟລ໌"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ອຸປະກອນຖືກລັອກໂດຍຜູ້ເບິ່ງແຍງລະບົບ"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ອຸປະກອນຖືກສັ່ງໃຫ້ລັອກ"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">ອຸປະກອນບໍ່ໄດ້ຖືກປົດລັອກເປັນເວລາ <xliff:g id="NUMBER_1">%d</xliff:g> ຊົ່ວໂມງ. ຢືນຢັນແບບຮູບ.</item>
-      <item quantity="one">ອຸປະກອນບໍ່ໄດ້ຖືກປົດລັອກເປັນເວລາ <xliff:g id="NUMBER_0">%d</xliff:g> ຊົ່ວໂມງ. ຢືນຢັນແບບຮູບ.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">ອຸປະກອນບໍ່ໄດ້ຖືກປົດລັອກເປັນເວລາ <xliff:g id="NUMBER_1">%d</xliff:g> ຊົ່ວໂມງ. ຢືນຢັນ PIN</item>
-      <item quantity="one">ອຸປະກອນບໍ່ໄດ້ຖືກປົດລັອກເປັນເວລາ <xliff:g id="NUMBER_0">%d</xliff:g> ຊົ່ວໂມງ. ຢືນຢັນ PIN</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">ອຸປະກອນບໍ່ໄດ້ຖືກປົດລັອກເປັນເວລາ <xliff:g id="NUMBER_1">%d</xliff:g> ຊົ່ວໂມງ. ຢືນຢັນລະຫັດຜ່ານ.</item>
-      <item quantity="one">ອຸປະກອນບໍ່ໄດ້ຖືກປົດລັອກເປັນເວລາ <xliff:g id="NUMBER_0">%d</xliff:g> ຊົ່ວໂມງ. ຢືນຢັນລະຫັດຜ່ານ.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"ບໍ່ຮູ້ຈັກ"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"ບໍ່ຮູ້ຈັກ"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-lt/strings.xml b/packages/SystemUI/res-keyguard/values-lt/strings.xml
index 057eb45..20164a1 100644
--- a/packages/SystemUI/res-keyguard/values-lt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lt/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Klaviatūros apsauga"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Įveskite PIN kodą"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Įveskite SIM kortelės PUK kodą ir naują PIN kodą"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM kortelės PUK kodas"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Naujas SIM kortelės PIN kodas"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Palieskite, kad įves. slaptaž."</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Įveskite slaptažodį, kad atrakintumėte"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Įveskite PIN kodą, kad atrakintumėte"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Įveskite PIN kodą"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Nubrėžkite atrakinimo piešinį"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Įveskite slaptažodį"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Netinkamas PIN kodas."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Netinkama kortelė."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Įkrauta"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kraunama be laidų"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Greitai įkraunama"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lėtai įkraunama"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Įkrovimas laikinai apribotas"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Prijunkite kroviklį."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Paspauskite meniu, jei norite atrakinti."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tinklas užrakintas"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nėra SIM kortelės"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Įrenginio slaptažodis"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM kortelės PIN kodo sritis"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM kortelės PUK kodo sritis"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Kitas nustatytas signalas: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Ištrinti"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Išjungti eSIM kortelę"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Nepavyko išjungti „eSIM“ kortelės"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Dėl klaidos nepavyko išjungti „eSIM“ kortelės."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Pamiršau atrakinimo piešinį"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Netinkamas atrakinimo piešinys"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Netinkamas slaptažodis"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Netinkamas PIN kodas"</string>
@@ -70,12 +58,9 @@
       <item quantity="many">Bandykite dar kartą po <xliff:g id="NUMBER">%d</xliff:g> sekundės.</item>
       <item quantity="other">Bandykite dar kartą po <xliff:g id="NUMBER">%d</xliff:g> sekundžių.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Nupieškite atrakinimo piešinį"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Įveskite SIM kortelės PIN kodą."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Įveskite „<xliff:g id="CARRIER">%1$s</xliff:g>“ SIM kortelės PIN kodą"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Išjunkite eSIM kortelę ir naudokite įrenginį be mobiliojo ryšio paslaugos."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Įveskite PIN kodą"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Įveskite slaptažodį"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Dabar SIM neleidžiama. Jei norite tęsti, įveskite PUK kodą. Jei reikia išsamios informacijos, susisiekite su operatoriumi."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"„<xliff:g id="CARRIER">%1$s</xliff:g>“ SIM kortelė išjungta. Jei norite tęsti, įveskite PUK kodą. Jei reikia išsamios informacijos, susisiekite su operatoriumi."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Įveskite pageidaujamą PIN kodą"</string>
@@ -83,8 +68,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Atrakinama SD kortelė..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Įveskite PIN kodą, sudarytą iš 4–8 skaičių."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kodas turėtų būti sudarytas iš 8 ar daugiau skaitmenų."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Pakartotinai įveskite tinkamą PUK kodą. Pakartotinai bandant SIM kortelė bus išjungta visam laikui."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Per daug atrakinimo piešinių bandymų"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai įvedėte PIN kodą. \n\nBandykite dar kartą po <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai įvedėte slaptažodį. \n\nBandykite dar kartą po <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"<xliff:g id="NUMBER_0">%1$d</xliff:g> kart. netinkamai nupiešėte atrakinimo piešinį. \n\nBandykite dar kartą po <xliff:g id="NUMBER_1">%2$d</xliff:g> sek."</string>
@@ -104,8 +87,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Nepavyko atlikti SIM kortelės PIN kodo operacijos."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Nepavyko atlikti SIM kortelės PUK kodo operacijos."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kodas priimtas!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Nėra paslaugos."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Perjungti įvesties metodą"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Lėktuvo režimas"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Iš naujo paleidus įrenginį būtinas atrakinimo piešinys"</string>
@@ -114,29 +95,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Norint užtikrinti papildomą saugą būtinas atrakinimo piešinys"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Norint užtikrinti papildomą saugą būtinas PIN kodas"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Norint užtikrinti papildomą saugą būtinas slaptažodis"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Perjungiant profilius būtinas atrakinimo piešinys"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Perjungiant profilius būtinas PIN kodas"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Perjungiant profilius būtinas slaptažodis"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Įrenginį užrakino administratorius"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Įrenginys užrakintas neautomatiškai"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandą. Patvirtinkite atrakinimo piešinį.</item>
-      <item quantity="few">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandas. Patvirtinkite atrakinimo piešinį.</item>
-      <item quantity="many">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandos. Patvirtinkite atrakinimo piešinį.</item>
-      <item quantity="other">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandų. Patvirtinkite atrakinimo piešinį.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandą. Patvirtinkite PIN kodą.</item>
-      <item quantity="few">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandas. Patvirtinkite PIN kodą.</item>
-      <item quantity="many">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandos. Patvirtinkite PIN kodą.</item>
-      <item quantity="other">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandų. Patvirtinkite PIN kodą.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandą. Patvirtinkite slaptažodį.</item>
-      <item quantity="few">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandas. Patvirtinkite slaptažodį.</item>
-      <item quantity="many">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandos. Patvirtinkite slaptažodį.</item>
-      <item quantity="other">Įrenginys nebuvo atrakintas <xliff:g id="NUMBER_1">%d</xliff:g> valandų. Patvirtinkite slaptažodį.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Neatpažinta"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Neatpažinta"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-lv/strings.xml b/packages/SystemUI/res-keyguard/values-lv/strings.xml
index 6b474bd..238b706 100644
--- a/packages/SystemUI/res-keyguard/values-lv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-lv/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Taustiņslēgs"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Ievadiet PIN kodu."</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Ievadiet SIM kartes PUK kodu un jauno PIN kodu."</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM kartes PUK kods"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Jaunais SIM kartes PIN kods"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Piesk., lai ievadītu paroli"</font>"."</string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Ievadiet paroli, lai atbloķētu."</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Ievadiet PIN kodu, lai atbloķētu."</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Ievadiet savu PIN kodu"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Ievadiet savu kombināciju"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Ievadiet paroli"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN kods nav pareizs."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Nederīga karte."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Akumulators uzlādēts"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek bezvadu uzlāde"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek ātrā uzlāde"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Notiek lēnā uzlāde"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Uzlāde īslaicīgi ierobežota"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Pievienojiet lādētāju."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lai atbloķētu, nospiediet izvēlnes ikonu."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tīkls ir bloķēts."</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nav SIM kartes."</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Ierīces parole"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM kartes PIN apgabals"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM kartes PUK apgabals"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Nākamā signāla atskaņošanas laiks: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Dzēšanas taustiņš"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Atspējot eSIM karti"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Nevar atspējot eSIM karti"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Kļūdas dēļ nevar atspējot eSIM karti."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Ievadīšanas taustiņš"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Aizmirsu kombināciju"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Nepareiza kombinācija"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Nepareiza parole"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Nepareizs PIN kods."</string>
@@ -69,12 +57,9 @@
       <item quantity="one">Mēģiniet vēlreiz pēc <xliff:g id="NUMBER">%d</xliff:g> sekundes.</item>
       <item quantity="other">Mēģiniet vēlreiz pēc <xliff:g id="NUMBER">%d</xliff:g> sekundēm.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Zīmējiet savu kombināciju."</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Ievadiet SIM kartes PIN kodu."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Ievadiet SIM kartes “<xliff:g id="CARRIER">%1$s</xliff:g>” PIN kodu."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Atspējojiet eSIM karti, lai ierīci varētu izmantot bez mobilā pakalpojuma."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Ievadiet PIN."</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Ievadiet paroli"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM karte ir atspējota. Lai turpinātu, ievadiet PUK kodu. Lai iegūtu detalizētu informāciju, sazinieties ar mobilo sakaru operatoru."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM karte “<xliff:g id="CARRIER">%1$s</xliff:g>” ir atspējota. Lai turpinātu, ievadiet PUK kodu. Lai iegūtu detalizētu informāciju, sazinieties ar mobilo sakaru operatoru."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Ievadiet vēlamo PIN kodu."</string>
@@ -82,8 +67,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Notiek SIM kartes atbloķēšana..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Ievadiet PIN kodu, kas sastāv no 4 līdz 8 cipariem."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kodam ir jābūt vismaz 8 ciparus garam."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Atkārtoti ievadiet pareizo PUK kodu. Ja vairākas reizes ievadīsiet to nepareizi, SIM karte tiks neatgriezeniski atspējota."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Pārāk daudz kombinācijas mēģinājumu"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) esat ievadījis nepareizu PIN kodu.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundes(-ēm)."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) esat ievadījis nepareizu paroli.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundes(-ēm)."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Jūs <xliff:g id="NUMBER_0">%1$d</xliff:g> reizi(-es) esat nepareizi uzzīmējis atbloķēšanas kombināciju.\n\nMēģiniet vēlreiz pēc <xliff:g id="NUMBER_1">%2$d</xliff:g> sekundes(-ēm)."</string>
@@ -101,8 +84,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM kartes PIN koda ievadīšana neizdevās!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM kartes PUK koda ievadīšana neizdevās!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kods ir pieņemts!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Nav pakalpojuma."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Pārslēgt ievades metodi"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Lidojuma režīms"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Pēc ierīces restartēšanas ir jāievada atbloķēšanas kombinācija."</string>
@@ -111,26 +92,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Papildu drošībai ir jāievada atbloķēšanas kombinācija."</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Papildu drošībai ir jāievada PIN kods."</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Papildu drošībai ir jāievada parole."</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Pārslēdzot profilus, ir jāievada atbloķēšanas kombinācija."</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Pārslēdzot profilus, ir jāievada PIN kods."</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Pārslēdzot profilus, ir jāievada parole."</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administrators bloķēja ierīci."</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Ierīce tika bloķēta manuāli."</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="zero">Ierīce nav tikusi atbloķēta <xliff:g id="NUMBER_1">%d</xliff:g> stundas. Apstipriniet kombināciju.</item>
-      <item quantity="one">Ierīce nav tikusi atbloķēta <xliff:g id="NUMBER_1">%d</xliff:g> stundu. Apstipriniet kombināciju.</item>
-      <item quantity="other">Ierīce nav tikusi atbloķēta <xliff:g id="NUMBER_1">%d</xliff:g> stundas. Apstipriniet kombināciju.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="zero">Ierīce nav tikusi atbloķēta <xliff:g id="NUMBER_1">%d</xliff:g> stundas. Apstipriniet PIN.</item>
-      <item quantity="one">Ierīce nav tikusi atbloķēta <xliff:g id="NUMBER_1">%d</xliff:g> stundu. Apstipriniet PIN.</item>
-      <item quantity="other">Ierīce nav tikusi atbloķēta <xliff:g id="NUMBER_1">%d</xliff:g> stundas. Apstipriniet PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="zero">Ierīce nav tikusi atbloķēta <xliff:g id="NUMBER_1">%d</xliff:g> stundas. Apstipriniet paroli.</item>
-      <item quantity="one">Ierīce nav tikusi atbloķēta <xliff:g id="NUMBER_1">%d</xliff:g> stundu. Apstipriniet paroli.</item>
-      <item quantity="other">Ierīce nav tikusi atbloķēta <xliff:g id="NUMBER_1">%d</xliff:g> stundas. Apstipriniet paroli.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nav atpazīts"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nav atpazīts"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-mk/strings.xml b/packages/SystemUI/res-keyguard/values-mk/strings.xml
index 95b0bc5..f4c3dde 100644
--- a/packages/SystemUI/res-keyguard/values-mk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mk/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Напишете го PIN-кодот"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Внесете PUK-код за SIM и нов PIN-код"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK-код за SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Нов PIN-код за SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Допрете за да напишете лозинка"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Напишете ја лозинката за да отклучите"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Напишете PIN-код за да отклучите"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Внесете го PIN-кодот"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Внесете ја шемата"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Внесете ја лозинката"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Погрешен PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Неважечка картичка."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Полна"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Се полни безжично"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо полнење"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бавно полнење"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Полнењето е привремено ограничено"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Поврзете го полначот."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притиснете „Мени“ за отклучување."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежата е заклучена"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Нема SIM-картичка"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Лозинка за уред"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Поле за PIN на SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Поле за PUK на SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Следниот аларм е поставен во <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Избриши"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Оневозможи ја eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Не може да се оневозможи eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM-картичката не може да се оневозможи поради грешка."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Внеси"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Ја заборавивте шемата?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Погрешна шема"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Погрешна лозинка"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Погрешен PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">Обидете се повторно за <xliff:g id="NUMBER">%d</xliff:g> секунда.</item>
       <item quantity="other">Обидете се повторно за <xliff:g id="NUMBER">%d</xliff:g> секунди.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Нацртајте ја шемата"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Внесете PIN на SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Внесете PIN на SIM за „<xliff:g id="CARRIER">%1$s</xliff:g>“."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Оневозможете ја eSIM-картичката за да го користите уредот без мобилна услуга."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Внесете PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Внесете лозинка"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM-картичката сега е оневозможена. Внесете PUK-код за да продолжите. Контактирајте со операторот за детали."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM-картичката на <xliff:g id="CARRIER">%1$s</xliff:g> сега е оневозможена. Внесете PUK-код за да продолжите. Контактирајте со операторот за детали."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Внесете го саканиот PIN-код"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Се отклучува SIM-картичката…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Внесете PIN што содржи 4 - 8 броеви."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-кодот треба да содржи 8 или повеќе броеви."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Повторно внесете го точниот PUK-код. Повторните обиди трајно ќе ја оневозможат SIM-картичката."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Премногу обиди со шема"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Погрешно сте го напишале вашиот PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. \n\nОбидете се повторно за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Погрешно сте ја напишале вашата лозинка <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. \n\nОбидете се повторно за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Погрешно сте ја нацртале вашата шема за отклучување <xliff:g id="NUMBER_0">%1$d</xliff:g> пати. \n\nОбидете се повторно за <xliff:g id="NUMBER_1">%2$d</xliff:g> секунди."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM-картичката не се отклучи со PIN-кодот!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM-картичката не се отклучи со PUK-кодот!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Кодот е прифатен!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Нема услуга."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Префрли метод за внесување"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Авионски режим"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Потребна е шема по рестартирање на уредот"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Потребна е шема за дополнителна безбедност"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Потребен е PIN-код за дополнителна безбедност"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Потребна е лозинка за дополнителна безбедност"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Потребна е шема кога менувате профили"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Потребен е PIN-код кога менувате профили"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Потребна е лозинка кога менувате профили"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Уредот е заклучен од администраторот"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Уредот е заклучен рачно"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Уредот не е отклучен веќе <xliff:g id="NUMBER_1">%d</xliff:g> час. Потврдете ја шемата.</item>
-      <item quantity="other">Уредот не е отклучен веќе <xliff:g id="NUMBER_1">%d</xliff:g> часа. Потврдете ја шемата.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Уредот не е отклучен веќе <xliff:g id="NUMBER_1">%d</xliff:g> час. Потврдете го PIN-кодот.</item>
-      <item quantity="other">Уредот не е отклучен веќе <xliff:g id="NUMBER_1">%d</xliff:g> часа. Потврдете го PIN-кодот.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Уредот не е отклучен веќе <xliff:g id="NUMBER_1">%d</xliff:g> час. Потврдете ја лозинката.</item>
-      <item quantity="other">Уредот не е отклучен веќе <xliff:g id="NUMBER_1">%d</xliff:g> часа. Потврдете ја лозинката.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Непознат"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Непознат"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ml/strings.xml b/packages/SystemUI/res-keyguard/values-ml/strings.xml
index 0871767..06228c6c 100644
--- a/packages/SystemUI/res-keyguard/values-ml/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ml/strings.xml
@@ -20,26 +20,16 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"കീഗാർഡ്"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"പിൻ കോഡ് ടൈപ്പുചെയ്യുക"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"സിം PUK-യും പുതിയ പിൻ കോഡും ടൈപ്പുചെയ്യുക"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"സിം PUK കോഡ്"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"പുതിയ സിം പിൻ കോഡ്"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"പാസ്‌വേഡ് ടൈപ്പുചെയ്യുന്നതിന് സ്‌പർശിക്കുക"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"അൺലോക്കുചെയ്യുന്നതിന് പാസ്‌വേഡ് ടൈപ്പുചെയ്യുക"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"അൺലോക്കുചെയ്യുന്നതിന് പിൻ ടൈപ്പുചെയ്യുക"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"പിൻ നൽകുക"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"നിങ്ങളുടെ പാറ്റേൺ നൽകുക"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"നിങ്ങളുടെ പാസ്‌വേഡ് നല്‍‌കുക"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"പിൻ കോഡ് തെറ്റാണ്."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"അസാധുവായ കാർഡ്."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"ചാർജായി"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വയർലെസ്സ് ആയി ചാർജ് ചെയ്യുന്നു"</string>
     <string name="keyguard_plugged_in" msgid="8169926454348380863">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജ് ചെയ്യുന്നു"</string>
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • വേഗത്തിൽ ചാർജ് ചെയ്യുന്നു"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • പതുക്കെ ചാർജ് ചെയ്യുന്നു"</string>
-    <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജ് ചെയ്യൽ താൽക്കാലികമായി പരിമിതപ്പെടുത്തിയിരിക്കുന്നു"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"നിങ്ങളുടെ ചാർജർ കണക്റ്റുചെയ്യുക."</string>
+    <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ചാർജിംഗ് താൽക്കാലികമായി പരിമിതപ്പെടുത്തിയിരിക്കുന്നു"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"അൺലോക്കുചെയ്യാൻ മെനു അമർത്തുക."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"നെറ്റ്‌വർക്ക് ലോക്കുചെയ്‌തു"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"സിം കാർഡില്ല"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"ഉപകരണ പാസ്‌വേഡ്"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"സിം ‌പിൻ ഏരിയ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"സിം PUK ഏരിയ"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"അടുത്ത അലാറം <xliff:g id="ALARM">%1$s</xliff:g>-ന് സജ്ജീകരിച്ചു"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"ഇല്ലാതാക്കുക"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM പ്രവർത്തനരഹിതമാക്കുക"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"ഇ-സിം പ്രവർത്തനരഹിതമാക്കാനാകുന്നില്ല"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"പിശക് കാരണം ഇ-സിം പ്രവർത്തനരഹിതമാക്കാനാകുന്നില്ല"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"എന്റർ"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"പാറ്റേൺ മറന്നു"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"പാറ്റേൺ തെറ്റാണ്"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"പാസ്‌വേഡ് തെറ്റാണ്"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"പിൻ തെറ്റാണ്"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> സെക്കൻഡുകൾക്കുള്ളിൽ വീണ്ടും ശ്രമിക്കുക.</item>
       <item quantity="one">ഒരു സെക്കൻഡിനുള്ളിൽ വീണ്ടും ശ്രമിക്കുക.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"നിങ്ങളുടെ പാറ്റേൺ വരയ്‌ക്കുക"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"സിം പിൻ നൽകുക."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" എന്ന കാരിയർക്കുള്ള സിം പിൻ നൽകുക."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> മൊ‌ബൈൽ സേവനമില്ലാതെ ഉപകരണം ഉപയോഗിക്കാൻ ഇ-സിം പ്രവർത്തനരഹിതമാക്കുക."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"പിൻ നൽകുക"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"പാസ്‌വേഡ് നൽകുക"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"സിം ഇപ്പോൾ പ്രവർത്തനരഹിതമാക്കി. തുടരുന്നതിന് PUK കോഡ് നൽകുക. വിശദാംശങ്ങൾക്ക് കാരിയറെ ബന്ധപ്പെടുക."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" സിം ഇപ്പോൾ പ്രവർത്തനരഹിതമാക്കി. തുടരുന്നതിന് PUK കോഡ് നൽകുക. വിശദാംശങ്ങൾക്ക് കാരിയറെ ബന്ധപ്പെടുക."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"താൽപ്പര്യപ്പെടുന്ന പിൻ കോഡ് നൽകുക"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"സിം കാർഡ് അൺലോക്കുചെയ്യുന്നു…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 മുതൽ 8 വരെ അക്കങ്ങളുള്ള ഒരു പിൻ ടൈപ്പുചെയ്യുക."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK കോഡിൽ 8 അല്ലെങ്കിൽ അതിലധികം സംഖ്യകൾ ഉണ്ടായിരിക്കണം."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"ശരിയായ PUK കോഡ് വീണ്ടും നൽകുക. ആവർത്തിച്ചുള്ള ശ്രമങ്ങൾ സിം ശാശ്വതമായി പ്രവർത്തനരഹിതമാക്കും."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"വളരെയധികം പാറ്റേൺ ശ്രമങ്ങൾ"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ പിൻ ‌തെറ്റായി ‌ടൈപ്പുചെയ്തു. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> സെക്കന്റിനു‌ശേഷം വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ നിങ്ങളുടെ പാസ്‌വേഡ് ‌തെറ്റായി ‌ടൈപ്പുചെയ്തു. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> സെക്കന്റിനു‌ശേഷം വീണ്ടും ശ്രമിക്കുക."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"നിങ്ങൾ <xliff:g id="NUMBER_0">%1$d</xliff:g> തവണ അൺലോക്ക് പാറ്റേൺ ‌തെറ്റായി ‌വരച്ചു. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> സെക്കന്റിനു‌ശേഷം വീണ്ടും ശ്രമിക്കുക."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"പിൻ ഉപയോഗിച്ച് സിം അൺലോക്കു‌ചെയ്യാനുള്ള ‌ശ്രമം പരാജയപ്പെട്ടു!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"PUK ഉപയോഗിച്ച് സിം അൺലോക്കു‌ചെയ്യാനുള്ള ‌ശ്രമം പരാജയപ്പെട്ടു!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"കോഡ് അംഗീകരിച്ചു!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"സേവനമില്ല"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ഇൻപുട്ട് രീതി മാറുക"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"ഫ്ലൈറ്റ് മോഡ്"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ഉപകരണം റീസ്റ്റാർട്ടായശേഷം ‌പാറ്റേൺ വരയ്‌ക്കേണ്ടതുണ്ട്"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"അധിക സുരക്ഷയ്ക്ക് പാറ്റേൺ ആവശ്യമാണ്"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"അധിക സുരക്ഷയ്ക്ക് പിൻ ആവശ്യമാണ്"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"അധിക സുരക്ഷയ്ക്ക് പാസ്‌വേഡ് ആവശ്യമാണ്"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"പ്രൊഫൈലുകൾ തമ്മിൽ മാറുമ്പോൾ പാറ്റേൺ വരയ്‌ക്കേണ്ടതുണ്ട്"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"പ്രൊഫൈലുകൾ തമ്മിൽ മാറുമ്പോൾ പിൻ നൽകേണ്ടതുണ്ട്"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"പ്രൊഫൈലുകൾ തമ്മിൽ മാറുമ്പോൾ പാസ്‌വേഡ് നൽകേണ്ടതുണ്ട്"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ഉപകരണം അഡ്‌മിൻ ലോക്കുചെയ്തു"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ഉപകരണം നേരിട്ട് ലോക്കുചെയ്തു"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">ഉപകരണം <xliff:g id="NUMBER_1">%d</xliff:g> മണിക്കൂറായി അൺലോക്ക് ചെയ്തിട്ടില്ല. പാറ്റേൺ സ്ഥിരീകരിക്കുക.</item>
-      <item quantity="one">ഉപകരണം <xliff:g id="NUMBER_0">%d</xliff:g> മണിക്കൂറായി അൺലോക്ക് ചെയ്തിട്ടില്ല. പാറ്റേൺ സ്ഥിരീകരിക്കുക.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">ഉപകരണം <xliff:g id="NUMBER_1">%d</xliff:g> മണിക്കൂറായി അൺലോക്ക് ചെയ്തിട്ടില്ല. പിൻ സ്ഥിരീകരിക്കുക.</item>
-      <item quantity="one">ഉപകരണം <xliff:g id="NUMBER_0">%d</xliff:g> മണിക്കൂറായി അൺലോക്ക് ചെയ്തിട്ടില്ല. പിൻ സ്ഥിരീകരിക്കുക.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">ഉപകരണം <xliff:g id="NUMBER_1">%d</xliff:g> മണിക്കൂറായി അൺലോക്ക് ചെയ്തിട്ടില്ല. പാസ്‌വേഡ് സ്ഥിരീകരിക്കുക.</item>
-      <item quantity="one">ഉപകരണം <xliff:g id="NUMBER_0">%d</xliff:g> മണിക്കൂറായി അൺലോക്ക് ചെയ്തിട്ടില്ല. പാസ്‌വേഡ് സ്ഥിരീകരിക്കുക.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"തിരിച്ചറിയുന്നില്ല"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"തിരിച്ചറിയുന്നില്ല"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-mn/strings.xml b/packages/SystemUI/res-keyguard/values-mn/strings.xml
index b4f709d..db1396b 100644
--- a/packages/SystemUI/res-keyguard/values-mn/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mn/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Түгжээний код"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"ПИН кодыг оруулна уу"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM-н PUK код болон шинэ ПИН кодыг оруулна уу"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM-н PUK код"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Шинэ SIM-н ПИН код"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Нууц үг оруулах бол хүрнэ үү"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Түгжээг тайлахын тулд нууц үгийг оруулна уу"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Түгжээг тайлахын тулд ПИН кодыг оруулна уу"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"ПИН-ээ оруулна уу"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Хээгээ оруулна уу"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Нууц үгээ оруулна уу"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"ПИН код буруу байна."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Карт хүчингүй байна."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Цэнэглэсэн"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Утасгүй цэнэглэж байна"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Хурдан цэнэглэж байна"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Удаан цэнэглэж байна"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Цэнэглэхийг түр хязгаарласан"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Цэнэглэгчээ холбоно уу."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Түгжээг тайлах бол цэсийг дарна уу."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сүлжээ түгжигдсэн"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM карт алга"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Төхөөрөмжийн нууц үг"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM-н ПИН кодын хэсэг"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM-н PUK кодын хэсэг"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Дараагийн сэрүүлгийг <xliff:g id="ALARM">%1$s</xliff:g>-д тавьсан"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Устгах"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM-г идэвхгүй болгох"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM-г идэвхгүй болгох боломжгүй"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Алдаа гарсан тул eSIM-г идэвхгүй болгох боломжгүй байна."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Оруулах"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Загварыг мартсан"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Хээ буруу байна"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Нууц үг буруу байна"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"ПИН код буруу байна"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> секундын дараа дахин оролдоно уу.</item>
       <item quantity="one">1 секундын дараа дахин оролдоно уу.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Загварыг оруулна уу"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM-н ПИН-г оруулна уу."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\"-н SIM-н ПИН-г оруулна уу."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Төхөөрөмжийг мобайл үйлчилгээгүйгээр ашиглахын тулд eSIM-г идэвхгүй болгоно уу."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"ПИН оруулна уу"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Нууц үг оруулна уу"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM идэвхгүй байна. Үргэлжлүүлэх бол PUK кодыг оруулна уу. Дэлгэрэнгүй мэдээлэл авах бол оператор компанитайгаа холбогдоно уу."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"-г идэвхгүй болголоо. Үргэлжлүүлэхийн тулд PUK кодыг оруулна уу. Дэлгэрэнгүй мэдээлэл авах бол оператор компанитайгаа холбогдоно уу."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Дурын ПИН код оруулна уу"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM картын түгжээг тайлж байна…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4-8 тооноос бүтэх ПИН-г оруулна уу."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK код 8-с цөөнгүй тооноос бүтнэ."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Зөв PUK кодыг дахин оруулна уу. Олон удаагийн оролдлого нь SIM-г хүчингүй болгоно."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Загварыг хэт олон удаа буруу оруулсан байна"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Та ПИН кодоо <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Та нууц үгээ <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу орууллаа. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM-н ПИН-г буруу орууллаа!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM-н PUK-г буруу орууллаа!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Кодыг зөв орууллаа!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Үйлчилгээ алга."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Оруулах аргыг сэлгэх"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Нислэгийн горим"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Төхөөрөмжийг дахин эхлүүлсний дараа загвар оруулах шаардлагатай"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Аюулгүй байдлын үүднээс загвар оруулах шаардлагатай"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Аюулгүй байдлын үүднээс ПИН оруулах шаардлагатай"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Аюулгүй байдлын үүднээс нууц үг оруулах шаардлагатай"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Профайлыг солиход загвар оруулах шаардлагатай"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Профайлыг солиход ПИН оруулах шаардлагатай"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Профайлыг сэлгэхэд нууц үг оруулах шаардлагатай"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Админ төхөөрөмжийг түгжсэн"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Төхөөрөмжийг гараар түгжсэн"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Төхөөрөмжийн түгжээг <xliff:g id="NUMBER_1">%d</xliff:g> цагийн турш тайлаагүй байна. Загварыг баталгаажуулна уу.</item>
-      <item quantity="one">Төхөөрөмжийн түгжээг <xliff:g id="NUMBER_0">%d</xliff:g> цагийн турш тайлаагүй байна. Загварыг баталгаажуулна уу.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Төхөөрөмжийн түгжээг <xliff:g id="NUMBER_1">%d</xliff:g> цагийн турш тайлаагүй байна. ПИН кодоо баталгаажуулна уу.</item>
-      <item quantity="one">Төхөөрөмжийн түгжээг <xliff:g id="NUMBER_0">%d</xliff:g> цагийн турш тайлаагүй байна. ПИН кодоо баталгаажуулна уу.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Төхөөрөмжийн түгжээг <xliff:g id="NUMBER_1">%d</xliff:g> цагийн турш тайлаагүй байна. Нууц үгээ баталгаажуулна уу.</item>
-      <item quantity="one">Төхөөрөмжийн түгжээг <xliff:g id="NUMBER_0">%d</xliff:g> цагийн турш тайлаагүй байна. Нууц үгээ баталгаажуулна уу.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Таньж чадсангүй"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Таньж чадсангүй"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-mr/strings.xml b/packages/SystemUI/res-keyguard/values-mr/strings.xml
index 3079010..b83ef6bb 100644
--- a/packages/SystemUI/res-keyguard/values-mr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-mr/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"कीगार्ड"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"पिन कोड टाइप करा"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"सिम PUK आणि नवीन पिन कोड टाइप करा"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"सिम PUK कोड"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"नवीन सिम पिन कोड"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"पासवर्ड टाइप करण्यासाठी स्पर्श करा"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"अनलॉक करण्यासाठी पासवर्ड टाइप करा"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"अनलॉक करण्यासाठी पिन टाइप करा"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"तुमचा पिन एंटर करा"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"तुमचा पॅटर्न एंटर करा"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"तुमचा पासवर्ड एंटर करा"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"चुकीचा पिन कोड."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"अवैध कार्ड."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"चार्ज झाली"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वायरलेस पद्धतीने चार्ज करत आहे"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • वेगाने चार्ज होत आहे"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • सावकाश चार्ज होत आहे"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्जिंग तात्पुरते मर्यादित आहे"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"तुमचा चार्जर कनेक्ट करा."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलॉक करण्यासाठी मेनू दाबा."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लॉक केले"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"सिम कार्ड नाही"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"डिव्हाइस पासवर्ड"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"सिम पिन क्षेत्र"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"सिम PUK क्षेत्र"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"पुढील अलार्म <xliff:g id="ALARM">%1$s</xliff:g> साठी सेट केला"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"हटवा"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM बंद करा"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM बंद करू नका"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"एका एररमुळे eSIM बंद होऊ शकत नाही."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"एंटर करा"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"पॅटर्न विसरलात"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"चुकीचा पॅटर्न"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"चुकीचा पासवर्ड"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"चुकीचा पिन"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> सेकंदांत पुन्हा प्रयत्न करा.</item>
       <item quantity="one">एका सेकंदात पुन्‍हा प्रयत्न करा.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"तुमचा पॅटर्न काढा"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"सिम पिन एंटर करा"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" साठी सिम पिन एंटर करा"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> मोबाइल सेवेशिवाय डिव्हाइस वापरण्यासाठी eSIM बंद करा."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"पिन एंटर करा"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"पासवर्ड एंटर करा"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"सिम आता अक्षम केले आहे. सुरू ठेवण्यासाठी PUK कोड एंटर करा. तपशीलांसाठी वाहकाशी संपर्क साधा."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" सिम आता अक्षम केले आहे. सुरू ठेवण्यासाठी PUK कोड एंटर करा. तपशीलांसाठी वाहकाशी संपर्क साधा."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"इच्छित पिन कोड एंटर करा"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"सिम कार्ड अनलॉक करत आहे…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 ते 8 अंकांचा पिन टाईप करा."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK कोड 8 अंकी किंवा त्यापेक्षा अधिकचा असावा."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"योग्य PUK कोड पुन्हा एंटर करा. पुनःपुन्हा प्रयत्न करणे सिम कायमचे अक्षम करेल."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"खूप जास्त पॅटर्न प्रयत्न"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"तुम्ही तुमचा PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने टाइप केला आहे. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"तुम्ही तुमचा पासवर्ड <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा चुकीच्या पद्धतीने टाइप केला आहे. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"तुम्ही तुमचा अनलॉक पॅटर्न <xliff:g id="NUMBER_0">%1$d</xliff:g> वेळा अयोग्यरितीने काढला. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकंदांमध्ये पुन्हा प्रयत्न करा."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"सिम पिन ऑपरेशन अयशस्वी झाले!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"सिम PUK कार्य अयशस्‍वी झाले!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"कोड स्‍वीकारला!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"सेवा नाही."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"इनपुट पद्धत स्विच करा"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"विमान मोड"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"डिव्हाइस रीस्टार्ट झाल्यावर पॅटर्न आवश्यक आहे"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"अतिरिक्त सुरक्षिततेसाठी पॅटर्न आवश्‍यक आहे"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"अतिरिक्त सुरक्षिततेसाठी पिन आवश्‍यक आहे"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"अतिरिक्त सुरक्षिततेसाठी पासवर्ड आवश्‍यक आहे"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"तुम्ही प्रोफाईल स्विच करता तेव्‍हा पॅटर्न आवश्‍यक आहे"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"तुम्ही प्रोफाईल स्विच करता तेव्‍हा पिन आवश्‍यक आहे"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"तुम्ही प्रोफाईल स्विच करता तेव्‍हा पासवर्ड आवश्‍यक आहे"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"प्रशासकाद्वारे लॉक केलेले डिव्हाइस"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"डिव्हाइस मॅन्युअली लॉक केले होते"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पॅटर्नची खात्री करा.</item>
-      <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_0">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पॅटर्नची खात्री करा.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पिन ची खात्री करा.</item>
-      <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_0">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पिनची खात्री करा.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">डिव्हाइस <xliff:g id="NUMBER_1">%d</xliff:g> तासांसाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item>
-      <item quantity="one">डिव्हाइस <xliff:g id="NUMBER_0">%d</xliff:g> तासासाठी अनलॉक केले गेले नाही. पासवर्डची खात्री करा.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"ओळखले नाही"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"ओळखले नाही"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ms/strings.xml b/packages/SystemUI/res-keyguard/values-ms/strings.xml
index 6092cc7..4205a2d 100644
--- a/packages/SystemUI/res-keyguard/values-ms/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ms/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Pengawal kekunci"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Taip kod PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Taip PUK SIM dan kod PIN baharu"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Kod PUK SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Kod PIN SIM baharu"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Sentuh untuk menaip kata laluan"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Taip kata laluan untuk membuka kunci"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Taip PIN untuk membuka kunci"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Masukkan PIN anda"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Masukkan corak anda"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Masukkan kata laluan anda"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Kod PIN salah."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Kad Tidak Sah."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Sudah dicas"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas secara wayarles"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan cepat"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mengecas dengan perlahan"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pengecasan terhad sementara"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Sambungkan pengecas anda."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Tekan Menu untuk membuka kunci."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rangkaian dikunci"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Tiada kad SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Kata laluan peranti"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Bahagian PIN SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Bahagian PUK SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Penggera seterusnya ditetapkan pada <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Padam"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Lumpuhkan eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Tidak dapat melumpuhkan eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM tidak dapat dilumpuhkan kerana ralat."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Kekunci Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Terlupa Corak"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Corak salah"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Kata laluan salah"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN salah"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Cuba lagi dalam masa <xliff:g id="NUMBER">%d</xliff:g> saat.</item>
       <item quantity="one">Cuba lagi dalam masa 1 saat.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Lukis corak anda"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Masukkan PIN SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Masukkan PIN SIM untuk \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Lumpuhkan eSIM untuk menggunakan peranti tanpa perkhidmatan mudah alih."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Masukkan PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Masukkan Kata Laluan"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM kini dilumpuhkan. Masukkan kod PUK untuk meneruskan. Hubungi pembawa untuk mendapatkan butiran."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" kini dilumpuhkan. Masukkan kod PUK untuk meneruskan. Hubungi pembawa untuk mendapatkan butiran."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Masukkan kod PIN yang diingini"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Membuka kunci kad SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Taipkan PIN yang mengandungi 4 hingga 8 nombor."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Kod PUK seharusnya 8 nombor atau lebih."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Masukkan semula kod PUK yang betul. Percubaan berulang akan melumpuhkan SIM secara kekal."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Terlalu banyak percubaan melukis corak"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Anda telah tersilap taip PIN sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. \n\nCuba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> saat."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Anda telah tersilap taip kata laluan sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. \n\nCuba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> saat."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Anda telah tersilap lukis corak buka kunci sebanyak <xliff:g id="NUMBER_0">%1$d</xliff:g> kali. \n\nCuba lagi dalam <xliff:g id="NUMBER_1">%2$d</xliff:g> saat."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Pengendalian PIN SIM gagal!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Pengendalian PUK SIM gagal!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kod Diterima!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Tiada perkhidmatan."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Tukar kaedah masukan"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Mod Pesawat"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Corak diperlukan setelah peranti dimulakan semula"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Corak diperlukan untuk keselamatan tambahan"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN diperlukan untuk keselamatan tambahan"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Kata laluan diperlukan untuk keselamatan tambahan"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Corak diperlukan apabila anda menukar profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PIN diperlukan apabila anda menukar profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Kata laluan diperlukan apabila anda menukar profil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Peranti dikunci oleh pentadbir"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Peranti telah dikunci secara manual"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Peranti tidak dibuka kuncinya selama <xliff:g id="NUMBER_1">%d</xliff:g> jam. Sahkan corak.</item>
-      <item quantity="one">Peranti tidak dibuka kuncinya selama <xliff:g id="NUMBER_0">%d</xliff:g> jam. Sahkan corak.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Peranti tidak dibuka kuncinya selama <xliff:g id="NUMBER_1">%d</xliff:g> jam. Sahkan PIN.</item>
-      <item quantity="one">Peranti tidak dibuka kuncinya selama <xliff:g id="NUMBER_0">%d</xliff:g> jam. Sahkan PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Peranti tidak dibuka kuncinya selama <xliff:g id="NUMBER_1">%d</xliff:g> jam. Sahkan kata laluan.</item>
-      <item quantity="one">Peranti tidak dibuka kuncinya selama <xliff:g id="NUMBER_0">%d</xliff:g> jam. Sahkan kata laluan.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Tidak dikenali"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Tidak dikenali"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-my/strings.xml b/packages/SystemUI/res-keyguard/values-my/strings.xml
index 71729cf..6ce5c05 100644
--- a/packages/SystemUI/res-keyguard/values-my/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-my/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"လုံခြုံရေးကီး"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"ပင်နံပါတ်ထည့်ပါ"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"ဆင်းမ် ပင်နံပါတ် ပြန်ဖွင့်သည့်ကုဒ်နှင့် ပင်နံပါတ်အသစ် ထည့်ပါ"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"ဆင်းမ် ပင်နံပါတ် ပြန်ဖွင့်သည့်ကုဒ်"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"ဆင်းမ် ပင်နံပါတ်အသစ်"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"စကားဝှက် ရိုက်ရန် ထိပါ"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"လော့ခ်ဖွင့်ရန် စကားဝှက်ကို ထည့်ပါ"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"လော့ခ်ဖွင့်ရန် ပင်နံပါတ်ထည့်ပါ"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"သင့်ပင်နံပါတ် ထည့်ပါ"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"သင့်လော့ခ်ဖွင့်ပုံစံ ထည့်ပါ"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"သင့်စကားဝှက် ထည့်ပါ"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"ပင်နံပါတ် မှားနေသည်။"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ကတ် မမှန်ကန်ပါ။"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"အားသွင်းပြီးပါပြီ"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ကြိုးမဲ့ အားသွင်းနေသည်"</string>
@@ -39,28 +30,25 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အမြန်အားသွင်းနေသည်"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • နှေးကွေးစွာ အားသွင်းနေသည်"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • အားသွင်းခြင်းကို လောလောဆယ် ကန့်သတ်ထားသည်"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"အားသွင်းကိရိယာကို ချိတ်ဆက်ပါ။"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"မီနူးကို နှိပ်၍ လော့ခ်ဖွင့်ပါ။"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ကွန်ရက်ကို လော့ခ်ချထားသည်"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ဆင်းမ်ကတ် မရှိပါ"</string>
     <string name="keyguard_missing_sim_instructions" msgid="1162120926141335918">"ဆင်းမ်ကတ် ထည့်ပါ။"</string>
-    <string name="keyguard_missing_sim_instructions_long" msgid="2712623293749378570">"ဆင်းမ်ကဒ်မရှိပါ သို့မဟုတ် အသုံးပြု၍မရပါ။ ဆင်းမ်ကဒ်တစ်ခု ထည့်ပါ။"</string>
+    <string name="keyguard_missing_sim_instructions_long" msgid="2712623293749378570">"ဆင်းမ်ကတ်မရှိပါ သို့မဟုတ် အသုံးပြု၍မရပါ။ ဆင်းမ်ကတ်တစ်ခု ထည့်ပါ။"</string>
     <string name="keyguard_permanent_disabled_sim_message_short" msgid="5842745213110966962">"အသုံးပြု၍ မရတော့သော ဆင်းမ်ကတ်။"</string>
-    <string name="keyguard_permanent_disabled_sim_instructions" msgid="2490584154727897806">"သင့်ဆင်းမ်ကဒ်ကို အပြီးအပိုင် ပိတ်လိုက်ပါပြီ။\n နောက်ထပ်ဆင်းမ်ကဒ်တစ်ခု ရယူရန်အတွက် သင်၏ ကြိုးမဲ့ဝန်ဆောင်မှုပေးသူထံ ဆက်သွယ်ပါ။"</string>
+    <string name="keyguard_permanent_disabled_sim_instructions" msgid="2490584154727897806">"သင့်ဆင်းမ်ကတ်ကို အပြီးအပိုင် ပိတ်လိုက်ပါပြီ။\n နောက်ထပ်ဆင်းမ်ကတ်တစ်ခု ရယူရန်အတွက် သင်၏ ကြိုးမဲ့ဝန်ဆောင်မှုပေးသူထံ ဆက်သွယ်ပါ။"</string>
     <string name="keyguard_sim_locked_message" msgid="4343544458476911044">"ဆင်းမ်ကတ် လော့ခ်ကျနေပါသည်။"</string>
-    <string name="keyguard_sim_puk_locked_message" msgid="6253830777745450550">"ဆင်းမ်ကဒ်သည် ပင်နံပါတ် ပြန်ဖွင့်သည့်ကုဒ် လော့ခ်ကျနေပါသည်။"</string>
-    <string name="keyguard_sim_unlock_progress_dialog_message" msgid="2394023844117630429">"ဆင်းမ်ကဒ်ကို လော့ခ်ဖွင့်နေပါသည်…"</string>
+    <string name="keyguard_sim_puk_locked_message" msgid="6253830777745450550">"ဆင်းမ်ကတ်သည် ပင်နံပါတ် ပြန်ဖွင့်သည့်ကုဒ် လော့ခ်ကျနေပါသည်။"</string>
+    <string name="keyguard_sim_unlock_progress_dialog_message" msgid="2394023844117630429">"ဆင်းမ်ကတ်ကို လော့ခ်ဖွင့်နေပါသည်…"</string>
     <string name="keyguard_accessibility_pin_area" msgid="7403009340414014734">"ပင်နံပါတ်နေရာ"</string>
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"စက်စကားဝှက်"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"ဆင်းမ်ပင်နံပါတ်နေရာ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"ဆင်းမ် ပင်နံပါတ် ပြန်ဖွင့်သည့်ကုဒ် နေရာ"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"နောက်နှိုးစက်အချိန်ကို <xliff:g id="ALARM">%1$s</xliff:g> တွင် သတ်မှတ်ထားပါသည်"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"ဖျက်ရန်"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM ကို ပိတ်ရန်"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM ကို ပိတ်၍မရခြင်း"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"အမှားအယွင်းရှိနေသောကြောင့် eSIM ကို ပိတ်၍မရပါ။"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter ခလုတ်"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"ပုံစံအား မေ့သွားပါသည်"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"လော့ခ်ဖွင့်ပုံစံ မှားနေသည်"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"စကားဝှက် မှားနေသည်"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"ပင်နံပါတ် မမှန်ကန်ပါ"</string>
@@ -68,21 +56,16 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> စက္ကန့် အကြာတွင် ထပ်လုပ်ကြည့်ပါ</item>
       <item quantity="one">၁ စက္ကန့် အကြာတွင် ထပ်လုပ်ကြည့်ပါ</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"ပုံစံကို ဆွဲပါ"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"ဆင်းမ်ကတ် ပင်နံပါတ်ကို ထည့်ပါ။"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" အတွက် ဆင်းမ်ကဒ်ပင်နံပါတ်ကို ထည့်ပါ။"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> မိုဘိုင်းဝန်ဆောင်မှု မရှိဘဲ စက်ပစ္စည်းကို အသုံးပြုရန် eSIM ကို ပိတ်ပါ။"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"ပင်နံပါတ်ကို ထည့်ပါ"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"စကားဝှက်ကို ထည့်ပါ"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"ဆင်းမ်ကဒ်သည် ယခု ပိတ်သွားပါပြီ။ ရှေ့ဆက်ရန် ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ်ကို ထည့်ပါ။ ပိုမိုလေ့လာရန် မိုဘိုင်းဝန်ဆောင်မှုပေးသူကို ဆက်သွယ်နိုင်ပါသည်။"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" ဆင်းမ်ကို ယခု ပိတ်လိုက်ပါပြီ။ ရှေ့ဆက်ရန် ပင်နံပါတ် ပြန်ဖွင့်သည့်ကုဒ်ကို ထည့်ပါ။ အသေးစိတ် အချက်အလက်များအတွက် မိုဘိုင်းဝန်ဆောင်မှုပေးသူထံ ဆက်သွယ်ပါ။"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"မိမိလိုလားသော ပင်နံပါတ်ကို ထည့်ပါ"</string>
     <string name="kg_enter_confirm_pin_hint" msgid="4261064020391799132">"မိမိလိုလားသော ပင်နံပါတ်ကို အတည်ပြုပါ"</string>
-    <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"ဆင်းမ်ကဒ်ကို လော့ခ်ဖွင့်နေပါသည်…"</string>
+    <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"ဆင်းမ်ကတ်ကို လော့ခ်ဖွင့်နေပါသည်…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"ဂဏန်း ၄ လုံးမှ ၈ လုံးအထိ ရှိသော ပင်နံပါတ်ကို ထည့်ပါ။"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"ပင်နံပါတ် ပြန်ဖွင့်သည့်ကုဒ်သည် ဂဏန်း ၈ လုံးနှင့် အထက် ဖြစ်ရပါမည်။"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"မှန်ကန်သည့် ပင်နံပါတ် ပြန်ဖွင့်သည့်ကုဒ်ကို ပြန်ထည့်ပါ။ ထပ်ခါထပ်ခါမှားယွင်းနေလျှင် ဆင်းမ်ကဒ်ကို အပြီးအပိုင် ပိတ်လိုက်ပါမည်။"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"ပုံစံထည့်သွင်းရန် ကြိုးစားသည့် အကြိမ်အရေအတွက် အလွန်များနေပါပြီ"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"သင်သည် ပင်နံပါတ်ကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ်မှားယွင်းစွာ ထည့်ခဲ့ပါသည်။ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"သင်သည် စကားဝှက်ကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ်မှားယွင်းစွာ ထည့်ခဲ့ပါသည်။ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"သင်သည် ပုံစံကို <xliff:g id="NUMBER_0">%1$d</xliff:g> ကြိမ်မှားယွင်းစွာ ဆွဲခဲ့ပါသည်။ \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> စက္ကန့်အကြာတွင် ထပ်စမ်းကြည့်ပါ။"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"ဆင်းမ်ကဒ်ပင်နံပါတ် လုပ်ဆောင်ချက် မအောင်မြင်ပါ။"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"ဆင်းမ်ကတ် ပင်နံပါတ် ပြန်ဖွင့်သည့်ကုဒ် လုပ်ဆောင်ချက် မအောင်မြင်ပါ။"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"ကုဒ်ကို လက်ခံလိုက်ပါပြီ။"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"ဝန်ဆောင်မှု မရှိပါ။"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"စာရိုက်စနစ်ပြောင်းရန်"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"လေယာဉ်ပျံမုဒ်"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"စက်ပစ္စည်းကို ပိတ်ပြီးပြန်ဖွင့်လိုက်သည့်အခါတွင် ပုံစံ လိုအပ်ပါသည်"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ပိုမို၍ လုံခြုံမှု ရှိစေရန် ပုံစံ လိုအပ်ပါသည်"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ပိုမို၍ လုံခြုံမှု ရှိစေရန် ပင်နံပါတ် လိုအပ်ပါသည်"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ပိုမို၍ လုံခြုံမှု ရှိစေရန် စကားဝှက် လိုအပ်ပါသည်"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"ပရိုဖိုင်များကို ပြောင်းသည့်အခါ ပုံစံ လိုအပ်ပါသည်"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"ပရိုဖိုင်များကို ပြောင်းသည့်အခါ ပင်နံပါတ် လိုအပ်ပါသည်"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"ပရိုဖိုင်များကို ပြောင်းသည့်အခါ စကားဝှက် လိုအပ်ပါသည်"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"စက်ပစ္စည်းကို စီမံခန့်ခွဲသူက လော့ခ်ချထားပါသည်"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"စက်ပစ္စည်းကို ကိုယ်တိုင်ကိုယ်ကျ လော့ခ်ချထားခဲ့သည်"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">စက်ပစ္စည်းကို <xliff:g id="NUMBER_1">%d</xliff:g> နာရီကြာ လော့ခ်ဖွင့်ခဲ့ခြင်း မရှိပါ။ ပုံစံအား အတည်ပြုပါ။</item>
-      <item quantity="one">စက်ပစ္စည်းကို <xliff:g id="NUMBER_0">%d</xliff:g> နာရီကြာ လော့ခ်ဖွင့်ခဲ့ခြင်း မရှိပါ။ ပုံစံအား အတည်ပြုပါ။</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">စက်ပစ္စည်းကို <xliff:g id="NUMBER_1">%d</xliff:g> နာရီကြာ လော့ခ်ဖွင့်ခဲ့ခြင်း မရှိပါ။ ပင်နံပါတ်အား အတည်ပြုပါ။</item>
-      <item quantity="one">စက်ပစ္စည်းကို <xliff:g id="NUMBER_0">%d</xliff:g> နာရီကြာ လော့ခ်ဖွင့်ခဲ့ခြင်း မရှိပါ။ ပင်နံပါတ်အား အတည်ပြုပါ။</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">စက်ပစ္စည်းကို <xliff:g id="NUMBER_1">%d</xliff:g> နာရီကြာ လော့ခ်ဖွင့်ခဲ့ခြင်း မရှိပါ။ စကားဝှက်အား အတည်ပြုပါ။</item>
-      <item quantity="one">စက်ပစ္စည်းကို <xliff:g id="NUMBER_0">%d</xliff:g> နာရီကြာ လော့ခ်ဖွင့်ခဲ့ခြင်း မရှိပါ။ စကားဝှက်အား အတည်ပြုပါ။</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"မသိ"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"မသိ"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-nb/strings.xml b/packages/SystemUI/res-keyguard/values-nb/strings.xml
index edc849a..890afc0 100644
--- a/packages/SystemUI/res-keyguard/values-nb/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nb/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Tastaturlås"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Skriv inn PIN-koden"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Skriv inn PUK-koden for SIM-kortet og en ny PIN-kode"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK-koden for SIM-kortet"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Ny PIN-kode for SIM-kortet"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Trykk for å skrive inn passord"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Skriv inn passordet for å låse opp"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Skriv inn PIN-koden for å låse opp"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Skriv inn PIN-koden din"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Legg inn mønsteret ditt"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Skriv inn passordet ditt"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Feil PIN-kode."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ugyldig kort."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Oppladet"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader trådløst"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader raskt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lader sakte"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Lading er midlertidig begrenset"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Koble til en batterilader."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Trykk på menyknappen for å låse opp."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nettverket er låst"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM-kort mangler"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Enhetspassord"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"PIN-området for SIM-kortet"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"PUK-området for SIM-kortet"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Neste alarm er stilt inn for <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Slett"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Deaktiver e-SIM-kortet"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Kan ikke deaktivere e-SIM-kortet"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"E-SIM-kortet kan ikke deaktiveres på grunn av en feil."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Har du glemt mønsteret?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Feil mønster"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Feil passord"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Feil PIN-kode"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Prøv på nytt om <xliff:g id="NUMBER">%d</xliff:g> sekunder.</item>
       <item quantity="one">Prøv på nytt om ett sekund.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Tegn mønsteret ditt"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Skriv inn PIN-koden for SIM-kortet."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Skriv inn PIN-koden for SIM-kortet «<xliff:g id="CARRIER">%1$s</xliff:g>»."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Deaktiver e-SIM-kortet for å bruke enheten uten mobiltjeneste."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Skriv inn PIN-koden"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Skriv inn passordet"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM-kortet er nå deaktivert. Skriv inn PUK-koden for å fortsette. Ta kontakt med operatøren for mer informasjon."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM-kortet «<xliff:g id="CARRIER">%1$s</xliff:g>» er nå deaktivert. Skriv inn PUK-koden for å fortsette. Ta kontakt med operatøren for mer informasjon."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Tast inn ønsket PIN-kode"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Låser opp SIM-kortet …"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Skriv inn en PIN-kode på fire til åtte sifre."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-koden skal være på åtte eller flere sifre."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Skriv inn den riktige PUK-koden på nytt. Gjentatte forsøk deaktiverer SIM-kortet permanent."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"For mange forsøk på tegning av mønster"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Du har oppgitt feil PIN-kode <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. \n\nPrøv på nytt om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Du har tastet inn passordet ditt feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. \n\nPrøv på nytt om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Du har tegnet opplåsningsmønsteret ditt feil <xliff:g id="NUMBER_0">%1$d</xliff:g> ganger. \n\nPrøv på nytt om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"PIN-koden for SIM-kortet ble avvist."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"PUK-koden for SIM-kortet ble avvist."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Koden er godkjent."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Ingen tilkobling."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Bytt inndatametode"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Flymodus"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Du må tegne mønsteret etter at enheten har startet på nytt"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Du må tegne mønsteret for ekstra sikkerhet"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Du må skrive inn PIN-koden for ekstra sikkerhet"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Du må skrive inn passordet for ekstra sikkerhet"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Du må tegne mønsteret når du bytter profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Du må skrive inn PIN-koden når du bytter profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Du må skrive inn passordet når du bytter profil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Enheten er låst av administratoren"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Enheten ble låst manuelt"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Enheten har ikke blitt låst opp de siste <xliff:g id="NUMBER_1">%d</xliff:g> timene. Bekreft mønsteret.</item>
-      <item quantity="one">Enheten har ikke blitt låst opp på <xliff:g id="NUMBER_0">%d</xliff:g> time. Bekreft mønsteret.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Enheten har ikke blitt låst opp de siste <xliff:g id="NUMBER_1">%d</xliff:g> timene. Bekreft PIN-koden.</item>
-      <item quantity="one">Enheten har ikke blitt låst opp på <xliff:g id="NUMBER_0">%d</xliff:g> time. Bekreft PIN-koden.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Enheten har ikke blitt låst opp de siste <xliff:g id="NUMBER_1">%d</xliff:g> timene. Bekreft passordet.</item>
-      <item quantity="one">Enheten har ikke blitt låst opp på <xliff:g id="NUMBER_0">%d</xliff:g> time. Bekreft passordet.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Ikke gjenkjent"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ikke gjenkjent"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ne/strings.xml b/packages/SystemUI/res-keyguard/values-ne/strings.xml
index 0692aef..57d9d95 100644
--- a/packages/SystemUI/res-keyguard/values-ne/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ne/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"किगार्ड"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"PIN कोड टाइप गर्नुहोस्"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM को PUK कोड र नयाँ PIN कोड टाइप गर्नुहोस्"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM को PUK कोड"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"SIM को नयाँ PIN कोड"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"पासवर्ड टाइप गर्न छुनुहोस्"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"अनलक गर्न पासवर्ड टाइप गर्नुहोस्"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"अनलक गर्न PIN कोड टाइप गर्नुहोस्"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"आफ्नो PIN प्रविष्टि गर्नुहोस्"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"आफ्नो ढाँचा प्रविष्टि गर्नुहोस्"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"आफ्नो पासवर्ड प्रविष्ट गर्नु…"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN कोड गलत छ।"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"अमान्य कार्ड।"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"चार्ज भयो"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • तारविनै चार्ज गर्दै"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • द्रुत गतिमा चार्ज गरिँदै छ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • मन्द गतिमा चार्ज गरिँदै"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • चार्जिङ केही समयका लागि सीमित पारिएको छ"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"तपाईंको चार्जर जोड्नुहोस्।"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"अनलक गर्न मेनु थिच्नुहोस्।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"नेटवर्क लक भएको छ"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM कार्ड छैन"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"डिभाइसको पासवर्ड"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM को PIN क्षेत्र"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM को PUK क्षेत्र"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"अर्को अलार्म <xliff:g id="ALARM">%1$s</xliff:g> का लागि सेट गरियो"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"मेट्नुहोस्"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM लाई असक्षम पार्नुहोस्"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM लाई असक्षम पार्न सकिएन"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"कुनै त्रुटिका कारण यो eSIM लाई असक्षम पार्न सकिएन।"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"प्रविष्टि गर्नुहोस्"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"ढाँचा बिर्सनुभयो"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"प्याटर्न मिलेन"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"गलत पासवर्ड"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"गलत PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> सेकेन्डपछि फेरि प्रयास गर्नुहोस्।</item>
       <item quantity="one">१ सेकेन्डपछि फेरि प्रयास गर्नुहोस्।</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"आफ्नो ढाँचा कोर्नुहोस्"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM को PIN प्रविष्टि गर्नुहोस्।"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" को SIM को PIN प्रविष्टि गर्नुहोस्।"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> मोबाइल सेवा बिना डिभाइसको प्रयोग गर्न eSIM लाई असक्षम पार्नुहोस्।"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"PIN प्रविष्टि गर्नुहोस्"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"पासवर्ड प्रविष्टि गर्नुहोस्"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM कार्ड अहिले असक्षम छ। सुचारु गर्नको लागि PUK कोड प्रविष्टि गर्नुहोस्।  विवरणको लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM <xliff:g id="CARRIER">%1$s</xliff:g> अहिले असक्षम छ। सुचारु गर्नको लागि PUK कोड प्रविष्टि गर्नुहोस्। विवरणका लागि सेवा प्रदायकलाई सम्पर्क गर्नुहोस्।"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"रूचाइएको PIN कोड प्रविष्टि गर्नुहोस्"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM कार्ड अनलक गरिँदै..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"४ देखि ८ वटा नम्बर भएको एउटा PIN टाइप गर्नुहोस्।"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK कोड ८ वा सो भन्दा बढी नम्बरको हुनु पर्छ।"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"PUK कोड पुन: प्रविष्टि गर्नुहोस्। पटक-पटकको प्रयासले SIM सदाका लागि असक्षम हुनेछ।"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"अत्यन्त धेरै ढाँचा कोर्ने प्रयासहरू"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले आफ्नो PIN प्रविष्ट गर्नुभएको छ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक आफ्नो गलत पासवर्ड  प्रविष्ट गर्नुभएको छ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि प्रयास गर्नुहोस्।"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"तपाईंले <xliff:g id="NUMBER_0">%1$d</xliff:g> पटक गलत तरिकाले आफ्नो अनलक प्याटर्न कोर्नुभएको छ। \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> सेकेन्डमा फेरि कोसिस गर्नुहोस्।"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM को PIN कोड राखेर अनलक गर्ने कार्य असफल भयो!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM को PUK कोड राखेर अनलक गर्ने कार्य असफल भयो!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"कोड स्वीकृत भयो!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"सेवा उपलब्ध छैन।"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"इनपुट विधिलाई स्विच गर्नुहोस्"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"हवाइजहाज मोड"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"यन्त्र पुनः सुरु भएपछि ढाँचा आवश्यक पर्दछ"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"अतिरिक्त सुरक्षाको लागि ढाँचा आवश्यक छ"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"अतिरिक्त सुरक्षाको लागि PIN आवश्यक छ"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"अतिरिक्त सुरक्षाको लागि पासवर्ड आवश्यक छ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"तपाईंले प्रोफाइलहरू स्विच गर्नुहुँदा ढाँचा आवश्यक पर्दछ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"तपाईंले प्रोफाइलहरू स्विच गर्नुहुँदा PIN आवश्यक पर्दछ"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"तपाईंले प्रोफाइलहरू स्विच गर्नुहुँदा पासवर्ड आवश्यक पर्दछ"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"प्रशासकले यन्त्रलाई लक गर्नुभएको छ"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"यन्त्रलाई म्यानुअल तरिकाले लक गरिएको थियो"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">यन्त्र <xliff:g id="NUMBER_1">%d</xliff:g> घन्टा देखि अनलक भएको छैन। ढाँचा पुष्टि गर्नुहोस्।</item>
-      <item quantity="one">यन्त्र <xliff:g id="NUMBER_0">%d</xliff:g> घन्टा देखि अनलक भएको छैन। ढाँचा पुष्टि गर्नुहोस्।</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">यन्त्र <xliff:g id="NUMBER_1">%d</xliff:g> घन्टा देखि अनलक भएको छैन। PIN पुष्टि गर्नुहोस्।</item>
-      <item quantity="one">यन्त्र <xliff:g id="NUMBER_0">%d</xliff:g> घन्टा देखि अनलक भएको छैन। PIN पुष्टि गर्नुहोस्।</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">यन्त्र <xliff:g id="NUMBER_1">%d</xliff:g> घन्टा देखि अनलक भएको छैन। पासवर्ड पुष्टि गर्नुहोस्।</item>
-      <item quantity="one">यन्त्र <xliff:g id="NUMBER_0">%d</xliff:g> घन्टा देखि अनलक भएको छैन। पासवर्ड पुष्टि गर्नुहोस्।</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"पहिचान भएन"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"पहिचान भएन"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-nl/strings.xml b/packages/SystemUI/res-keyguard/values-nl/strings.xml
index 45343ed..11f29ef 100644
--- a/packages/SystemUI/res-keyguard/values-nl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-nl/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Toetsblokkering"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Typ pincode"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Typ de pukcode voor de simkaart en de nieuwe pincode"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Pukcode voor simkaart"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nieuwe pincode voor simkaart"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Tik om wachtwoord te typen"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Typ het wachtwoord om te ontgrendelen"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Typ pincode om te ontgrendelen"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Geef je pincode op"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Geef je patroon op"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Geef je wachtwoord op"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Onjuiste pincode."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ongeldige kaart."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Opgeladen"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Draadloos opladen"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Snel opladen"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Langzaam opladen"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Opladen tijdelijk beperkt"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Sluit de oplader aan."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Druk op Menu om te ontgrendelen."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Netwerk vergrendeld"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Geen simkaart"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Apparaatwachtwoord"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Gebied voor pincode van simkaart"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Gebied voor pukcode van simkaart"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Volgende wekker ingesteld voor <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Delete"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"E-simkaart uitzetten"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"E-simkaart kan niet worden uitgezet"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"De e-simkaart kan niet worden uitgezet vanwege een fout."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Patroon vergeten"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Onjuist patroon"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Onjuist wachtwoord"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Onjuiste pincode"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Probeer het over <xliff:g id="NUMBER">%d</xliff:g> seconden opnieuw.</item>
       <item quantity="one">Probeer het over één seconde opnieuw.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Teken je patroon"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Geef de pincode van de simkaart op."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Geef de pincode voor de simkaart van \'<xliff:g id="CARRIER">%1$s</xliff:g>\' op."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Zet de e-simkaart uit om het apparaat te gebruiken zonder mobiele service."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Geef je pincode op"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Geef je wachtwoord op"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"De simkaart is nu uitgezet. Geef de pukcode op om door te gaan. Neem contact op met de provider voor informatie."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Simkaart van <xliff:g id="CARRIER">%1$s</xliff:g> is nu uitgezet. Geef de pukcode op om door te gaan. Neem contact op met je provider voor meer informatie."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Geef de gewenste pincode op"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Simkaart ontgrendelen…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Geef een pincode van vier tot acht cijfers op."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"De pukcode is minimaal acht cijfers lang."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Geef de juiste pukcode opnieuw op. Bij herhaalde pogingen wordt de simkaart definitief uitgezet."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Te veel patroonpogingen"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Je hebt je pincode <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getypt. \n\nProbeer het over <xliff:g id="NUMBER_1">%2$d</xliff:g> seconden opnieuw."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Je hebt je wachtwoord <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getypt. \n\nProbeer het over <xliff:g id="NUMBER_1">%2$d</xliff:g> seconden opnieuw."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Je hebt je ontgrendelingspatroon <xliff:g id="NUMBER_0">%1$d</xliff:g> keer onjuist getekend. \n\nProbeer het over <xliff:g id="NUMBER_1">%2$d</xliff:g> seconden opnieuw."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Bewerking met pincode voor simkaart is mislukt."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Bewerking met pukcode voor simkaart is mislukt."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Code geaccepteerd."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Geen service."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Invoermethode wijzigen"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Vliegtuigmodus"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Patroon vereist nadat het apparaat opnieuw is opgestart"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Patroon vereist voor extra beveiliging"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Pincode vereist voor extra beveiliging"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Wachtwoord vereist voor extra beveiliging"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Patroon is vereist wanneer je schakelt tussen profielen"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Pincode is vereist wanneer je schakelt tussen profielen"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Wachtwoord is vereist wanneer je schakelt tussen profielen"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Apparaat vergrendeld door beheerder"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Apparaat is handmatig vergrendeld"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Apparaat is al <xliff:g id="NUMBER_1">%d</xliff:g> uur niet ontgrendeld. Bevestig het patroon.</item>
-      <item quantity="one">Apparaat is al <xliff:g id="NUMBER_0">%d</xliff:g> uur niet ontgrendeld. Bevestig het patroon.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Apparaat is al <xliff:g id="NUMBER_1">%d</xliff:g> uur niet ontgrendeld. Bevestig de pincode.</item>
-      <item quantity="one">Apparaat is al <xliff:g id="NUMBER_0">%d</xliff:g> uur niet ontgrendeld. Bevestig de pincode.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Apparaat is al <xliff:g id="NUMBER_1">%d</xliff:g> uur niet ontgrendeld. Bevestig het wachtwoord.</item>
-      <item quantity="one">Apparaat is al <xliff:g id="NUMBER_0">%d</xliff:g> uur niet ontgrendeld. Bevestig het wachtwoord.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Niet herkend"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Niet herkend"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-or/strings.xml b/packages/SystemUI/res-keyguard/values-or/strings.xml
index 33fd58c..8a6c2449 100644
--- a/packages/SystemUI/res-keyguard/values-or/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-or/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"କୀ’ଗାର୍ଡ"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"PIN କୋଡ୍‍ ଟାଇପ୍‍ କରନ୍ତୁ"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM PUK ଓ ନୂଆ PIN କୋଡ୍‍ ଟାଇପ୍‍ କରନ୍ତୁ"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK କୋଡ୍‍"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"ନୂଆ SIM PIN କୋଡ୍‍"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"ପାସୱର୍ଡ ଟାଇପ୍‍ କରିବାକୁ ସ୍ପର୍ଶ କରନ୍ତୁ"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"ଅନଲକ୍‍ କରିବାକୁ ପାସ୍‌ୱର୍ଡ ଟାଇପ୍‍ କରନ୍ତୁ"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"ଅନଲକ୍‍ କରିବାକୁ PIN ଟାଇପ୍‍ କରନ୍ତୁ"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"ନିଜର PIN ଲେଖନ୍ତୁ"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"ନିଜର ପାଟର୍ନ ଆଙ୍କନ୍ତୁ"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"ନିଜ ପାସ୍‌ୱର୍ଡ ଲେଖନ୍ତୁ"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"ଭୁଲ PIN କୋଡ୍।"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ଅମାନ୍ୟ କାର୍ଡ।"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"ଚାର୍ଜ ହୋଇଗଲା"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"ୱାୟାର୍‍ଲେସ୍‍ଭାବରେ <xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜ ହୋଇଛି"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଦ୍ରୁତ ଭାବେ ଚାର୍ଜ ହେଉଛି"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ଚାର୍ଜିଂ ଅସ୍ଥାୟୀ ଭାବେ ସୀମିତ କରାଯାଇଛି"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"ଆପଣଙ୍କ ଚାର୍ଜର୍‍ ସଂଯୋଗ କରନ୍ତୁ।"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ଅନଲକ୍‌ କରିବା ପାଇଁ ମେନୁକୁ ଦବାନ୍ତୁ।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ନେଟୱର୍କକୁ ଲକ୍‌ କରାଯାଇଛି"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"କୌଣସି SIM କାର୍ଡ ନାହିଁ"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"ଡିଭାଇସ୍ ପାସ୍‍ୱର୍ଡ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN ଅଞ୍ଚଳ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK ଅଞ୍ଚଳ"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"<xliff:g id="ALARM">%1$s</xliff:g>ରେ ପରବର୍ତ୍ତୀ ଆଲାର୍ମ ସେଟ୍‍ କରାଯାଇଛି"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"ଡିଲିଟ୍‌ କରନ୍ତୁ"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM ଅକ୍ଷମ କରନ୍ତୁ"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIMକୁ ଅକ୍ଷମ କରାଯାଇପାରିବ ନାହିଁ"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"ଗୋଟିଏ ତ୍ରୁଟି କାରଣରୁ eSIMକୁ ଅକ୍ଷମ କରାଯାଇପାରିବ ନାହିଁ।"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"ଏଣ୍ଟର୍"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"ପାଟର୍ନ ଭୁଲି ଯାଇଛନ୍ତି"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"ଭୁଲ ପାଟର୍ନ"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"ଭୁଲ ପାସ୍‌ୱର୍ଡ"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"ଭୁଲ PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</item>
       <item quantity="one">1 ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"ନିଜ ପାଟର୍ନ ଆଙ୍କନ୍ତୁ"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIMର PIN ଲେଖନ୍ତୁ।"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" ପାଇଁ SIMର PIN ଲେଖନ୍ତୁ।"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> ବିନା ମୋବାଇଲ୍ ସେବାରେ ଡିଭାଇସ୍‌କୁ ବ୍ୟବହାର କରିବା ପାଇଁ eSIMକୁ ଅକ୍ଷମ କରନ୍ତୁ।"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"PIN ଲେଖନ୍ତୁ"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"ପାସ୍‌ୱର୍ଡ ଲେଖନ୍ତୁ"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM ବର୍ତ୍ତମାନ ଅକ୍ଷମ ଅଟେ। ଜାରି ରଖିବାକୁ PUK କୋଡ୍‍ ଏଣ୍ଟର୍ କରନ୍ତୁ। ବିବରଣୀ ପାଇଁ ନିଜ କେରିଅର୍‌ଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ବର୍ତ୍ତମାନ ଅକ୍ଷମ କରାଯାଇଛି। ଜାରିରଖିବାକୁ PUK କୋଡ୍‍ ଲେଖନ୍ତୁ। ବିବରଣୀ ପାଇଁ କେରିଅରଙ୍କ ସହ ଯୋଗାଯୋଗ କରନ୍ତୁ।"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"ନିଜ ଇଚ୍ଛାର PIN କୋଡ୍‍ ଲେଖନ୍ତୁ"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM କାର୍ଡ ଅନଲକ୍‍ କରାଯାଉଛି…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 ରୁ 8 ନମ୍ବର ବିଶିଷ୍ଟ ଏକ PIN ଟାଇପ୍ କରନ୍ତୁ।"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK କୋଡ୍‍‍ରେ 8ଟି କିମ୍ବା ଅଧିକ ନମ୍ବର ରହିଥାଏ।"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"ଠିକ୍‍ PUK କୋଡ୍‍ ପୁଣି ଲେଖନ୍ତୁ। ବାରମ୍ବାର ପ୍ରୟାସ କଲେ SIM କାର୍ଡ ସ୍ଥାୟୀ ରୂପେ ଅକ୍ଷମ ହୋଇଯିବ।"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"ଅନେକ ପାଟର୍ନ ପ୍ରୟାସ"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ଆପଣଙ୍କ PIN ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଟାଇପ୍‍ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ଆପଣଙ୍କ ପାସ୍‌ୱର୍ଡକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g> ଥର ଭୁଲ ଭାବେ ଟାଇପ୍ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ଆପଣଙ୍କ ଲକ୍‍ ଖୋଲିବା ପାଟର୍ନକୁ ଆପଣ <xliff:g id="NUMBER_0">%1$d</xliff:g>ଥର ଭୁଲ ଭାବେ ଅଙ୍କନ କରିଛନ୍ତି। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ସେକେଣ୍ଡ ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN କାମ ବିଫଳ ହେଲା!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUKର କାମ ବିଫଳ ହେଲା!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"କୋଡ୍‍ ସ୍ୱୀକାର କରାଗଲା!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"କୌଣସି ସେବା ନାହିଁ।"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ଇନପୁଟ୍‌ ପଦ୍ଧତି ବଦଳାନ୍ତୁ"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"ଏରୋପ୍ଲେନ୍‍ ମୋଡ୍"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ଡିଭାଇସ୍‍ ରିଷ୍ଟାର୍ଟ ହେବା ପରେ ପାଟର୍ନ ଆବଶ୍ୟକ ଅଟେ"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ ପାଟର୍ନ ଆବଶ୍ୟକ"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ PIN ଆବଶ୍ୟକ ଅଟେ"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ଅତିରିକ୍ତ ସୁରକ୍ଷା ପାଇଁ ପାସ୍‌ୱର୍ଡ ଆବଶ୍ୟକ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"ଆପଣ ପ୍ରୋଫାଇଲ୍‍ ବଦଳାଇବାବେଳେ ପାଟର୍ନ ଆବଶ୍ୟକ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"ଆପଣ ପ୍ରୋଫାଇଲ୍‍ ବଦଳାଇବା ବେଳେ PIN ଆବଶ୍ୟକ ଅଟେ"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"ଆପଣ ପ୍ରୋଫାଇଲ୍‍ ବଦଳାଇବାବେଳେ ପାସ୍‌ୱର୍ଡ ଆବଶ୍ୟକ"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ଡିଭାଇସ୍‍ ଆଡମିନଙ୍କ ଦ୍ୱାରା ଲକ୍‍ କରାଯାଇଛି"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ଡିଭାଇସ୍‍ ମାନୁଆଲ ଭାବେ ଲକ୍‍ କରାଗଲା"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> ଘଣ୍ଟା ପାଇଁ ଡିଭାଇସ୍‍ ଅନଲକ୍‍ କରାଯାଇନାହିଁ। ପାଟର୍ନ ସୁନିଶ୍ଚିତ କରନ୍ତୁ</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> ଘଣ୍ଟା ପାଇଁ ଡିଭାଇସ୍‍ ଅନଲକ୍‍ କରାଯାଇନାହିଁ। ପାଟର୍ନ ସୁନିଶ୍ଚିତ କରନ୍ତୁ</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> ଘଣ୍ଟା ପାଇଁ ଡିଭାଇସ୍‍ ଅନଲକ୍‍ କରାଯାଇ ନାହିଁ। PIN ନିଶ୍ଚିତ କରନ୍ତୁ</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> ଘଣ୍ଟା ପାଇଁ ଡିଭାଇସ୍‍ ଅନଲକ୍‍ କରାଯାଇ ନାହିଁ। PIN ନିଶ୍ଚିତ କରନ୍ତୁ</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> ଘଣ୍ଟା ପାଇଁ ଡିଭାଇସ୍‍ ଅନଲକ୍‍ କରାଯାଇ ନାହିଁ। ପାସୱର୍ଡ ସୁନିଶ୍ଚିତ କରନ୍ତୁ</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> ଘଣ୍ଟା ପାଇଁ ଡିଭାଇସ୍‍ ଅନଲକ୍‍ କରାଯାଇ ନାହିଁ। ପାସୱର୍ଡ ସୁନିଶ୍ଚିତ କରନ୍ତୁ</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"ଚିହ୍ନଟ ହେଲାନାହିଁ"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"ଚିହ୍ନଟ ହେଲାନାହିଁ"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-pa/strings.xml b/packages/SystemUI/res-keyguard/values-pa/strings.xml
index b3b14d7..f40e09e 100644
--- a/packages/SystemUI/res-keyguard/values-pa/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pa/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"ਕੀ-ਗਾਰਡ"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"ਪਿੰਨ ਕੋਡ ਟਾਈਪ ਕਰੋ"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"ਸਿਮ PUK ਅਤੇ ਨਵਾਂ ਪਿੰਨ ਕੋਡ ਟਾਈਪ ਕਰੋ"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"ਸਿਮ PUK ਕੋਡ"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"ਨਵਾਂ ਸਿਮ ਪਿੰਨ ਕੋਡ"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"ਪਾਸਵਰਡ ਟਾਈਪ ਕਰਨ ਲਈ ਸਪਰਸ਼ ਕਰੋ"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਪਾਸਵਰਡ ਟਾਈਪ ਕਰੋ"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"ਅਣਲਾਕ ਕਰਨ ਲਈ ਪਿੰਨ ਟਾਈਪ ਕਰੋ"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"ਆਪਣਾ ਪਿੰਨ ਦਾਖਲ ਕਰੋ"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"ਆਪਣਾ ਪੈਟਰਨ ਦਾਖਲ ਕਰੋ"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"ਆਪਣਾ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"ਗਲਤ ਪਿੰਨ ਕੋਡ।"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"ਅਵੈਧ ਕਾਰਡ।"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"ਚਾਰਜ ਹੋ ਗਿਆ"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਬਿਨਾਂ ਤਾਰ ਤੋਂ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਤੇਜ਼ੀ ਨਾਲ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਹੌਲੀ-ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ਚਾਰਜਿੰਗ ਕੁਝ ਸਮੇਂ ਲਈ ਰੋਕੀ ਗਈ"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"ਆਪਣਾ ਚਾਰਜਰ ਕਨੈਕਟ ਕਰੋ।"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"ਅਣਲਾਕ ਕਰਨ ਲਈ \"ਮੀਨੂ\" ਦਬਾਓ।"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ਨੈੱਟਵਰਕ  ਲਾਕ  ਕੀਤਾ ਗਿਆ"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ਕੋਈ ਸਿਮ ਕਾਰਡ ਨਹੀਂ"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"ਡੀਵਾਈਸ ਦਾ ਪਾਸਵਰਡ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"ਸਿਮ ਪਿੰਨ ਖੇਤਰ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK ਖੇਤਰ"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"ਅਗਲਾ ਅਲਾਰਮ <xliff:g id="ALARM">%1$s</xliff:g> \'ਤੇ ਸੈੱਟ ਕੀਤਾ ਗਿਆ"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"ਮਿਟਾਓ"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM ਨੂੰ ਅਯੋਗ ਬਣਾਓ"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"ਈ-ਸਿਮ ਬੰਦ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"ਕੋਈ ਗੜਬੜ ਹੋਣ ਕਰਕੇ ਈ-ਸਿਮ ਬੰਦ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"ਦਾਖਲ ਕਰੋ"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"ਪੈਟਰਨ ਭੁੱਲ ਗਏ"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"ਗਲਤ ਪੈਟਰਨ"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"ਗਲਤ ਪਾਸਵਰਡ"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"ਗਲਤ ਪਿੰਨ"</string>
@@ -68,12 +56,9 @@
       <item quantity="one"><xliff:g id="NUMBER">%d</xliff:g> ਸਕਿੰਟ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</item>
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> ਸਕਿੰਟ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"ਆਪਣਾ ਪੈਟਰਨ ਉਲੀਕੋ"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"ਸਿਮ ਪਿੰਨ ਦਾਖਲ ਕਰੋ।"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" ਲਈ ਸਿਮ ਪਿੰਨ ਦਾਖਲ ਕਰੋ।"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> ਮੋਬਾਈਲ ਸੇਵਾ ਤੋਂ ਬਿਨਾਂ ਡੀਵਾਈਸ ਨੂੰ ਵਰਤਣ ਲਈ ਈ-ਸਿਮ ਬੰਦ ਕਰੋ।"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"ਪਿੰਨ ਦਾਖਲ ਕਰੋ"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"ਸਿਮ ਹੁਣ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"ਸਿਮ \"<xliff:g id="CARRIER">%1$s</xliff:g>\" ਹੁਣ ਬੰਦ ਕੀਤਾ ਗਿਆ ਹੈ। ਜਾਰੀ ਰੱਖਣ ਲਈ PUK ਕੋਡ ਦਾਖਲ ਕਰੋ। ਵੇਰਵਿਆਂ ਲਈ ਕੈਰੀਅਰ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"ਇੱਛਤ ਪਿੰਨ ਕੋਡ ਦਾਖਲ ਕਰੋ"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM ਕਾਰਡ ਨੂੰ ਅਣਲਾਕ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"ਕੋਈ ਪਿੰਨ ਟਾਈਪ ਕਰੋ ਜੋ 4 ਤੋਂ 8 ਨੰਬਰਾਂ ਦਾ ਹੋਵੇ।"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK ਕੋਡ 8 ਜਾਂ ਵੱਧ ਨੰਬਰਾਂ ਦਾ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ।"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"ਸਹੀ PUK ਕੋਡ ਮੁੜ-ਦਾਖਲ ਕਰੋ। ਬਾਰ-ਬਾਰ ਕੀਤੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ ਸਿਮ ਨੂੰ ਸਥਾਈ ਤੌਰ \'ਤੇ ਬੰਦ ਕਰ ਦੇਣਗੀਆਂ।"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"ਬਹੁਤ ਜ਼ਿਆਦਾ ਪੈਟਰਨ ਕੋਸ਼ਿਸ਼ਾਂ"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ਤੁਸੀਂ ਆਪਣਾ ਪਿੰਨ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਪਾਸਵਰਡ ਗਲਤ ਢੰਗ ਨਾਲ ਟਾਈਪ ਕੀਤਾ ਹੈ।\n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ਤੁਸੀਂ <xliff:g id="NUMBER_0">%1$d</xliff:g> ਵਾਰ ਆਪਣਾ ਅਣਲਾਕ ਪੈਟਰਨ ਗਲਤ ਢੰਗ ਨਾਲ ਉਲੀਕਿਆ ਹੈ। \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> ਸਕਿੰਟਾਂ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"ਸਿਮ ਪਿੰਨ ਕਾਰਵਾਈ ਅਸਫਲ ਰਹੀ!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK ਕਾਰਵਾਈ ਅਸਫਲ ਰਹੀ!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"ਕੋਡ ਸਵੀਕਾਰ ਕੀਤਾ ਗਿਆ!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"ਕੋਈ ਸੇਵਾ ਨਹੀਂ।"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ਇਨਪੁੱਟ ਵਿਧੀ ਸਵਿੱਚ ਕਰੋ"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ਡੀਵਾਈਸ ਦੇ ਮੁੜ-ਚਾਲੂ ਹੋਣ \'ਤੇ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ ਪਿੰਨ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ਵਧੀਕ ਸੁਰੱਖਿਆ ਲਈ ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"ਜਦ ਤੁਸੀਂ ਪ੍ਰੋਫਾਈਲਾਂ ਨੂੰ ਸਵਿੱਚ ਕਰਦੇ ਹੋ ਤਾਂ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੈ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"ਜਦ ਤੁਸੀਂ ਪ੍ਰੋਫਾਈਲਾਂ ਨੂੰ ਸਵਿੱਚ ਕਰਦੇ ਹੋ ਤਾਂ ਪਿੰਨ ਦੀ ਲੋੜ ਹੈ"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"ਜਦ ਤੁਸੀਂ ਇੱਕ ਪ੍ਰੋਫਾਈਲ ਤੋਂ ਦੂਜੇ \'ਤੇ ਜਾਂਦੇ ਹੋ ਤਾਂ ਪਾਸਵਰਡ ਦੀ ਲੋੜ ਹੈ"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ਪ੍ਰਸ਼ਾਸਕ ਵੱਲੋਂ ਡੀਵਾਈਸ ਨੂੰ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"ਡੀਵਾਈਸ ਨੂੰ ਹੱਥੀਂ ਲਾਕ ਕੀਤਾ ਗਿਆ"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪੈਟਰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
-      <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪੈਟਰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਿੰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
-      <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਿੰਨ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ।</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟੇ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</item>
-      <item quantity="other">ਡੀਵਾਈਸ <xliff:g id="NUMBER_1">%d</xliff:g> ਘੰਟਿਆਂ ਤੋਂ ਅਣਲਾਕ ਨਹੀਂ ਕੀਤਾ ਗਿਆ ਹੈ। ਪਾਸਵਰਡ ਦੀ ਪੁਸ਼ਟੀ ਕਰੋ</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-pl/strings.xml b/packages/SystemUI/res-keyguard/values-pl/strings.xml
index 57f17e7..2d53dcc 100644
--- a/packages/SystemUI/res-keyguard/values-pl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pl/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Blokada klawiszy"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Wpisz kod PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Wpisz kod PUK i nowy kod PIN karty SIM"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Kod PUK karty SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nowy kod PIN karty SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Dotknij, by wpisać hasło"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Wpisz hasło, aby odblokować"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Wpisz kod PIN, aby odblokować"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Wpisz kod PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Narysuj wzór"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Wpisz hasło"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Nieprawidłowy kod PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Nieprawidłowa karta."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Naładowana"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie bezprzewodowe"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Szybkie ładowanie"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wolne ładowanie"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ładowanie tymczasowo ograniczone"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Podłącz ładowarkę."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Naciśnij Menu, aby odblokować."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieć zablokowana"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Brak karty SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Hasło urządzenia"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Miejsce na kod PIN karty SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Miejsce na kod PUK karty SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Następny alarm ustawiony na: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Usuń"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Wyłącz eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Nie można wyłączyć karty eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Nie można wyłączyć karty eSIM z powodu błędu."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Nie pamiętam wzoru"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Nieprawidłowy wzór"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Nieprawidłowe hasło"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Nieprawidłowy kod PIN"</string>
@@ -70,12 +58,9 @@
       <item quantity="other">Spróbuj ponownie za <xliff:g id="NUMBER">%d</xliff:g> sekundy.</item>
       <item quantity="one">Spróbuj ponownie za sekundę</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Narysuj wzór"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Wpisz kod PIN karty SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Wpisz kod PIN karty SIM „<xliff:g id="CARRIER">%1$s</xliff:g>”."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Wyłącz kartę eSIM, by używać urządzenia bez usługi sieci komórkowej."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Wpisz kod PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Wpisz hasło"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Karta SIM została wyłączona. Wpisz kod PUK, by przejść dalej. Skontaktuj się z operatorem, by uzyskać więcej informacji."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Karta SIM „<xliff:g id="CARRIER">%1$s</xliff:g>” została wyłączona. Wpisz kod PUK, by przejść dalej. Skontaktuj się z operatorem, by uzyskać więcej informacji."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Podaj wybrany kod PIN"</string>
@@ -83,8 +68,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Odblokowuję kartę SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Wpisz kod PIN o długości od 4 do 8 cyfr."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Kod PUK musi mieć co najmniej 8 cyfr."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Wpisz poprawny kod PUK. Kolejne próby spowodują trwałe wyłączenie karty SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Zbyt wiele prób narysowania wzoru"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> wpisałeś nieprawidłowy kod PIN. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> wpisałeś nieprawidłowe hasło. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Po raz <xliff:g id="NUMBER_0">%1$d</xliff:g> nieprawidłowo narysowałeś wzór odblokowania. \n\nSpróbuj ponownie za <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
@@ -104,8 +87,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Operacja z kodem PIN karty SIM nie udała się."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Operacja z kodem PUK karty SIM nie udała się."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kod został zaakceptowany."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Brak usługi."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Przełączanie metody wprowadzania"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Tryb samolotowy"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Po ponownym uruchomieniu urządzenia wymagany jest wzór"</string>
@@ -114,29 +95,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Dla większego bezpieczeństwa musisz narysować wzór"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Dla większego bezpieczeństwa musisz podać kod PIN"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Dla większego bezpieczeństwa musisz podać hasło"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Po przełączeniu profili wymagany jest wzór"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Po przełączeniu profili wymagany jest kod PIN"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Po przełączeniu profili wymagane jest hasło"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Urządzenie zablokowane przez administratora"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Urządzenie zostało zablokowane ręcznie"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="few">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_1">%d</xliff:g> godzin. Potwierdź wzór.</item>
-      <item quantity="many">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_1">%d</xliff:g> godzin. Potwierdź wzór.</item>
-      <item quantity="other">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_1">%d</xliff:g> godziny. Potwierdź wzór.</item>
-      <item quantity="one">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_0">%d</xliff:g> godziny. Potwierdź wzór.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="few">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_1">%d</xliff:g> godzin. Potwierdź kod PIN.</item>
-      <item quantity="many">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_1">%d</xliff:g> godzin. Potwierdź kod PIN.</item>
-      <item quantity="other">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_1">%d</xliff:g> godziny. Potwierdź kod PIN.</item>
-      <item quantity="one">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_0">%d</xliff:g> godziny. Potwierdź kod PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="few">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_1">%d</xliff:g> godzin. Potwierdź hasło.</item>
-      <item quantity="many">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_1">%d</xliff:g> godzin. Potwierdź hasło.</item>
-      <item quantity="other">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_1">%d</xliff:g> godziny. Potwierdź hasło.</item>
-      <item quantity="one">Urządzenie nie zostało odblokowane od <xliff:g id="NUMBER_0">%d</xliff:g> godziny. Potwierdź hasło.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nie rozpoznano"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nie rozpoznano"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
index c17b987..9fd9b1f 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Bloqueio do teclado"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Insira o código PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Digite o PUK do chip e o novo código PIN."</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Código PUK do chip"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Novo código PIN do chip"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Toque para inserir a senha"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Digite a senha para desbloquear"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Insira o PIN para desbloquear"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Digite seu PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Digite seu padrão"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Digite sua senha"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Código PIN incorreto."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cartão inválido."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Carregado"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando sem fio"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento temporariamente limitado"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecte o seu carregador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Sem chip"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Senha do dispositivo"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Área do PIN do chip"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Área do PUK do chip"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Próximo alarme definido para <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Excluir"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Desativar eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Não é possível desativar o eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Não é possível desativar o eSIM devido a um erro."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Inserir"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Esqueci o padrão"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Padrão incorreto"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Senha incorreta"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorreto"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">Tente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundo.</item>
       <item quantity="other">Tente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Desenhe seu padrão"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Informe o PIN do chip."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Informe o PIN do chip para \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desative o eSIM para usar o dispositivo sem serviço móvel."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Digite o PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Digite a senha"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"O chip foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para mais detalhes."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"O chip \"<xliff:g id="CARRIER">%1$s</xliff:g>\" foi desativado. Informe o código PUK para continuar. Entre em contato com a operadora para saber mais detalhes."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Digite o código PIN desejado"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Desbloqueando o chip…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Digite um PIN com 4 a 8 números."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"O código PUK deve ter oito números ou mais."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Introduza novamente o código PUK correto. Muitas tentativas malsucedidas desativarão permanentemente o chip."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Muitas tentativas de padrão"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Você digitou seu PIN incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Você digitou sua senha incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Falha na operação de PIN do chip."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Falha na operação de PUK do chip."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Código aceito."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Sem serviço."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Alterar o método de entrada"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Modo avião"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"O padrão é exigido após a reinicialização do dispositivo"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"O padrão é necessário para aumentar a segurança"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"O PIN é necessário para aumentar a segurança"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"A senha é necessária para aumentar a segurança"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"O padrão é exigido quando você troca de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"O PIN é exigido quando você troca de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"A senha é exigida quando você troca de perfil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloqueado pelo administrador"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"O dispositivo foi bloqueado manualmente"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> hora. Confirme o padrão.</item>
-      <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme o padrão.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> hora. Confirme o PIN.</item>
-      <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme o PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> hora. Confirme a senha.</item>
-      <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme a senha.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Não reconhecido"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Não reconhecido"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
index 2bc5dbb..da663f0 100644
--- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Introduza o código PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Introduza o PUK do cartão SIM e o novo código PIN"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Código PUK do cartão SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Novo código PIN do cartão SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Toque p/ introd. palavra-passe"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Introduza a palavra-passe para desbloquear"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Introduza o PIN para desbloquear"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Introduza o PIN."</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Introduza o padrão."</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introduza a palavra-passe."</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Código PIN incorreto."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cartão inválido."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Carregada"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar sem fios"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar rapidamente…"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • A carregar lentamente…"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento limitado temporariamente"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Ligue o carregador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Prima Menu para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nenhum cartão SIM"</string>
@@ -54,26 +44,21 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Palavra-passe do dispositivo"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Área do PIN do cartão SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Área do PUK do cartão SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Próximo alarme definido para <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Eliminar"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Desativar eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Não é possível desativar o eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Não é possível desativar o eSIM devido a um erro."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Tecla Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Esqueceu-se do padrão"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Padrão incorreto."</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Palavra-passe incorreta."</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorreto"</string>
     <plurals name="kg_too_many_failed_attempts_countdown" formatted="false" msgid="991400408675793914">
-      <item quantity="other">Tente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
       <item quantity="one">Tente novamente dentro de 1 segundo.</item>
+      <item quantity="other">Tente novamente dentro de <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Desenhe o seu padrão"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Introduza o PIN do cartão SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Introduza o PIN do cartão SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desative o eSIM para utilizar o dispositivo sem serviço móvel."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Introduza o PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Introduza a palavra-passe"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"O cartão SIM está agora desativado. Introduza o código PUK para continuar. Contacte o operador para obter mais detalhes."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"O cartão SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" está agora desativado. Introduza o código PUK para continuar. Contacte o operador para obter mais detalhes."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Introduza o código PIN pretendido"</string>
@@ -81,25 +66,21 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"A desbloquear o cartão SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Introduza um PIN com 4 a 8 números."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"O código PUK deve ter 8 ou mais números."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Volte a introduzir o código PUK correto. Demasiadas tentativas consecutivas irão desativar permanentemente o cartão SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Demasiadas tentativas para desenhar o padrão"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Introduziu o PIN incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Introduziu a palavra-passe incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Desenhou a sua padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Código PIN do cartão SIM incorreto. Tem de contactar o seu operador para desbloquear o dispositivo."</string>
     <plurals name="kg_password_wrong_pin_code" formatted="false" msgid="7030584350995485026">
-      <item quantity="other">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item>
       <item quantity="one">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de precisar de contactar o seu operador para desbloquear o dispositivo.</item>
+      <item quantity="other">Código PIN do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item>
     </plurals>
     <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"Cartão SIM inutilizável. Contacte o seu operador."</string>
     <plurals name="kg_password_wrong_puk_code" formatted="false" msgid="3937306685604862886">
-      <item quantity="other">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável.</item>
       <item quantity="one">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável.</item>
+      <item quantity="other">Código PUK do cartão SIM incorreto. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável.</item>
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Falha ao introduzir o PIN do cartão SIM!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Falha ao introduzir o PUK do cartão SIM!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Código aceite!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Sem serviço."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Alternar o método de introdução"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Modo de avião"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"É necessário um padrão após reiniciar o dispositivo"</string>
@@ -108,32 +89,17 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Para segurança adicional, é necessário um padrão"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Para segurança adicional, é necessário um PIN"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Para segurança adicional, é necessária uma palavra-passe"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"É necessário um padrão quando muda de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"É necessário um PIN quando muda de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"É necessária uma palavra-passe quando muda de perfil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloqueado pelo gestor"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"O dispositivo foi bloqueado manualmente"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme o padrão.</item>
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme o padrão.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme o PIN.</item>
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme o PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme a palavra-passe.</item>
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_0">%d</xliff:g> hora. Confirme a palavra-passe.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Não reconhecido."</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Não reconhecido."</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
-      <item quantity="other">Introduza o PIN do cartão SIM. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item>
       <item quantity="one">Introduza o PIN do cartão SIM. Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de ser necessário contactar o operador para desbloquear o dispositivo.</item>
+      <item quantity="other">Introduza o PIN do cartão SIM. Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas.</item>
     </plurals>
     <plurals name="kg_password_default_puk_message" formatted="false" msgid="571308542462946935">
-      <item quantity="other">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item>
       <item quantity="one">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item>
+      <item quantity="other">O SIM encontra-se desativado. Introduza o código PUK para continuar. Tem mais <xliff:g id="_NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.</item>
     </plurals>
     <string name="clock_title_default" msgid="6342735240617459864">"Predefinido"</string>
     <string name="clock_title_bubble" msgid="2204559396790593213">"Balão"</string>
diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml
index c17b987..9fd9b1f 100644
--- a/packages/SystemUI/res-keyguard/values-pt/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Bloqueio do teclado"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Insira o código PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Digite o PUK do chip e o novo código PIN."</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Código PUK do chip"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Novo código PIN do chip"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Toque para inserir a senha"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Digite a senha para desbloquear"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Insira o PIN para desbloquear"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Digite seu PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Digite seu padrão"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Digite sua senha"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Código PIN incorreto."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Cartão inválido."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Carregado"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando sem fio"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando rapidamente"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregando lentamente"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Carregamento temporariamente limitado"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Conecte o seu carregador."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pressione Menu para desbloquear."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rede bloqueada"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Sem chip"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Senha do dispositivo"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Área do PIN do chip"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Área do PUK do chip"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Próximo alarme definido para <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Excluir"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Desativar eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Não é possível desativar o eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Não é possível desativar o eSIM devido a um erro."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Inserir"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Esqueci o padrão"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Padrão incorreto"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Senha incorreta"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorreto"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">Tente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundo.</item>
       <item quantity="other">Tente novamente em <xliff:g id="NUMBER">%d</xliff:g> segundos.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Desenhe seu padrão"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Informe o PIN do chip."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Informe o PIN do chip para \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desative o eSIM para usar o dispositivo sem serviço móvel."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Digite o PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Digite a senha"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"O chip foi desativado. Insira o código PUK para continuar. Entre em contato com a operadora para mais detalhes."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"O chip \"<xliff:g id="CARRIER">%1$s</xliff:g>\" foi desativado. Informe o código PUK para continuar. Entre em contato com a operadora para saber mais detalhes."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Digite o código PIN desejado"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Desbloqueando o chip…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Digite um PIN com 4 a 8 números."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"O código PUK deve ter oito números ou mais."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Introduza novamente o código PUK correto. Muitas tentativas malsucedidas desativarão permanentemente o chip."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Muitas tentativas de padrão"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Você digitou seu PIN incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Você digitou sua senha incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Falha na operação de PIN do chip."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Falha na operação de PUK do chip."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Código aceito."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Sem serviço."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Alterar o método de entrada"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Modo avião"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"O padrão é exigido após a reinicialização do dispositivo"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"O padrão é necessário para aumentar a segurança"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"O PIN é necessário para aumentar a segurança"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"A senha é necessária para aumentar a segurança"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"O padrão é exigido quando você troca de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"O PIN é exigido quando você troca de perfil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"A senha é exigida quando você troca de perfil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispositivo bloqueado pelo administrador"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"O dispositivo foi bloqueado manualmente"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> hora. Confirme o padrão.</item>
-      <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme o padrão.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> hora. Confirme o PIN.</item>
-      <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme o PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> hora. Confirme a senha.</item>
-      <item quantity="other">O dispositivo não é desbloqueado há <xliff:g id="NUMBER_1">%d</xliff:g> horas. Confirme a senha.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Não reconhecido"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Não reconhecido"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ro/strings.xml b/packages/SystemUI/res-keyguard/values-ro/strings.xml
index fac6d7d..be6aea0 100644
--- a/packages/SystemUI/res-keyguard/values-ro/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ro/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Blocare tastatură"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Introduceți codul PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Introduceți codul PUK pentru cardul SIM și noul cod PIN"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Codul PUK pentru cardul SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Cod PIN nou pentru cardul SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Atingeți și introduceți parola"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Introduceți parola pentru a debloca"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Introduceți codul PIN pentru a debloca"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Introduceți codul PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Introduceți modelul"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Introduceți parola"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Cod PIN incorect."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Card nevalid"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Încărcată"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă wireless"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă rapid"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Se încarcă lent"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Încărcare limitată temporar"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Conectați încărcătorul."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Apăsați pe Meniu pentru a debloca."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rețea blocată"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Niciun card SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Parola dispozitivului"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Zona codului PIN pentru cardul SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Zona codului PUK pentru cardul SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Următoarea alarmă este setată pentru <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Ștergeți"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Dezactivați cardul eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Nu se poate dezactiva cardul eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Cardul eSIM nu poate fi dezactivat din cauza unei erori."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Introduceți"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Ați uitat modelul"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Model greșit"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Parolă greșită"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Cod PIN greșit"</string>
@@ -69,12 +57,9 @@
       <item quantity="other">Încercați din nou în <xliff:g id="NUMBER">%d</xliff:g> de secunde.</item>
       <item quantity="one">Încercați din nou într-o secundă.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Desenați modelul"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Introduceți codul PIN al cardului SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Introduceți codul PIN al cardului SIM pentru „<xliff:g id="CARRIER">%1$s</xliff:g>”."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Dezactivați cardul eSIM pentru a folosi dispozitivul fără serviciu mobil."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Introduceți codul PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Introduceți parola"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Cardul SIM este acum dezactivat. Pentru a continua, introduceți codul PUK. Pentru detalii, contactați operatorul."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Cardul SIM „<xliff:g id="CARRIER">%1$s</xliff:g>\" este acum dezactivat. Pentru a continua, introduceți codul PUK. Pentru detalii, contactați operatorul."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Introduceți codul PIN dorit"</string>
@@ -82,8 +67,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Se deblochează cardul SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Introduceți un cod PIN alcătuit din 4 până la 8 cifre."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Codul PUK trebuie să aibă minimum 8 cifre."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Reintroduceți codul PUK corect. Încercările repetate vor dezactiva definitiv cardul SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Prea multe încercări de desenare a modelului"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Ați introdus incorect codul PIN de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori.\n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> secunde."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Ați introdus incorect parola de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. \n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> secunde."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Ați desenat incorect modelul pentru deblocare de <xliff:g id="NUMBER_0">%1$d</xliff:g> ori. \n\nÎncercați din nou peste <xliff:g id="NUMBER_1">%2$d</xliff:g> secunde."</string>
@@ -101,8 +84,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Deblocarea cu ajutorul codului PIN pentru cardul SIM nu a reușit!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Deblocarea cu ajutorul codului PUK pentru cardul SIM nu a reușit!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Cod acceptat!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Fără serviciu."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Comutați metoda de introducere"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Mod Avion"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Modelul este necesar după repornirea dispozitivului"</string>
@@ -111,26 +92,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Modelul este necesar pentru securitate suplimentară"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Codul PIN este necesar pentru securitate suplimentară"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Parola este necesară pentru securitate suplimentară"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Modelul este necesar când comutați între profiluri"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Codul PIN este necesar când comutați între profiluri"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Parola este necesară când comutați între profiluri"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Dispozitiv blocat de administrator"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Dispozitivul a fost blocat manual"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="few">Dispozitivul nu a fost deblocat de <xliff:g id="NUMBER_1">%d</xliff:g> ore. Confirmați modelul.</item>
-      <item quantity="other">Dispozitivul nu a fost deblocat de <xliff:g id="NUMBER_1">%d</xliff:g> de ore. Confirmați modelul.</item>
-      <item quantity="one">Dispozitivul nu a fost deblocat de <xliff:g id="NUMBER_0">%d</xliff:g> oră. Confirmați modelul.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="few">Dispozitivul nu a fost deblocat de <xliff:g id="NUMBER_1">%d</xliff:g> ore. Confirmați codul PIN.</item>
-      <item quantity="other">Dispozitivul nu a fost deblocat de <xliff:g id="NUMBER_1">%d</xliff:g> de ore. Confirmați codul PIN.</item>
-      <item quantity="one">Dispozitivul nu a fost deblocat de <xliff:g id="NUMBER_0">%d</xliff:g> oră. Confirmați codul PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="few">Dispozitivul nu a fost deblocat de <xliff:g id="NUMBER_1">%d</xliff:g> ore. Confirmați parola.</item>
-      <item quantity="other">Dispozitivul nu a fost deblocat de <xliff:g id="NUMBER_1">%d</xliff:g> de ore. Confirmați parola.</item>
-      <item quantity="one">Dispozitivul nu a fost deblocat de <xliff:g id="NUMBER_0">%d</xliff:g> oră. Confirmați parola.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nu este recunoscută"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nu este recunoscut"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ru/strings.xml b/packages/SystemUI/res-keyguard/values-ru/strings.xml
index eb9d751..6e11d61 100644
--- a/packages/SystemUI/res-keyguard/values-ru/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ru/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Введите PIN-код"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Введите PUK-код и новый PIN-код"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK-код SIM-карты"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Новый PIN-код SIM-карты"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Нажмите для ввода пароля"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Введите пароль"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Введите PIN-код для разблокировки"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Введите PIN-код"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Введите графический ключ"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Введите пароль"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Неверный PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ошибка SIM-карты."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Батарея заряжена"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Беспроводная зарядка"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"Идет быстрая зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"Идет медленная зарядка (<xliff:g id="PERCENTAGE">%s</xliff:g>)"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Зарядка временно ограничена"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Подключите зарядное устройство."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Для разблокировки нажмите \"Меню\"."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Сеть заблокирована"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Нет SIM-карты."</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Пароль устройства"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"PIN-код SIM-карты"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"PUK-код SIM-карты"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Время следующего сигнала будильника: <xliff:g id="ALARM">%1$s</xliff:g>."</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Удалить"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Отключить eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Произошла ошибка"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Не удалось отключить eSIM."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Клавиша ввода"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Забыли графический ключ?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Неверный графический ключ"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Неверный пароль"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Неверный PIN-код"</string>
@@ -70,12 +58,9 @@
       <item quantity="many">Повторите попытку через <xliff:g id="NUMBER">%d</xliff:g> секунд.</item>
       <item quantity="other">Повторите попытку через <xliff:g id="NUMBER">%d</xliff:g> секунды.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Введите графический ключ"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Введите PIN-код SIM-карты."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Введите PIN-код SIM-карты \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Чтобы пользоваться устройством без мобильной связи, отключите eSIM."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Введите PIN-код"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Введите пароль"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM-карта отключена. Чтобы продолжить, введите PUK-код. За подробной информацией обратитесь к оператору связи."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM-карта \"<xliff:g id="CARRIER">%1$s</xliff:g>\" отключена. Чтобы продолжить, введите PUK-код. За подробной информацией обратитесь к оператору связи."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Введите PIN-код"</string>
@@ -83,8 +68,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Разблокировка SIM-карты…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Введите PIN-код (от 4 до 8 цифр)."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-код должен содержать не менее 8 цифр."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Введите правильный PUK-код. После нескольких неудачных попыток SIM-карта будет заблокирована."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Слишком много попыток ввести графический ключ."</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Вы ввели неверный PIN-код несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>).\n\nПовторите попытку через <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Вы ввели неверный пароль несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>).\n\nПовторите попытку через <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Вы начертили неверный графический ключ несколько раз (<xliff:g id="NUMBER_0">%1$d</xliff:g>).\n\nПовторите попытку через <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
@@ -104,8 +87,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Не удалось разблокировать SIM-карту"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Не удалось разблокировать SIM-карту"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Код принят"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Нет сигнала."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Сменить способ ввода"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Режим полета"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"После перезагрузки устройства необходимо ввести графический ключ"</string>
@@ -114,29 +95,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"В качестве дополнительной меры безопасности введите графический ключ"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"В качестве дополнительной меры безопасности введите PIN-код"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"В качестве дополнительной меры безопасности введите пароль"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"После смены профиля необходимо ввести графический ключ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"После смены профиля необходимо ввести PIN-код"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"После смены профиля необходимо ввести пароль"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Устройство заблокировано администратором"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Устройство было заблокировано вручную"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часа. Подтвердите графический ключ.</item>
-      <item quantity="few">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часов. Подтвердите графический ключ.</item>
-      <item quantity="many">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часов. Подтвердите графический ключ.</item>
-      <item quantity="other">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часа. Подтвердите графический ключ.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часа. Введите PIN-код ещё раз.</item>
-      <item quantity="few">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часов. Введите PIN-код ещё раз.</item>
-      <item quantity="many">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часов. Введите PIN-код ещё раз.</item>
-      <item quantity="other">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часа. Введите PIN-код ещё раз.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часа. Введите пароль ещё раз.</item>
-      <item quantity="few">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часов. Введите пароль ещё раз.</item>
-      <item quantity="many">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часов. Введите пароль ещё раз.</item>
-      <item quantity="other">Устройство не разблокировалось в течение <xliff:g id="NUMBER_1">%d</xliff:g> часа. Введите пароль ещё раз.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Не распознано"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Не распознано"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-si/strings.xml b/packages/SystemUI/res-keyguard/values-si/strings.xml
index 2267007..902127d 100644
--- a/packages/SystemUI/res-keyguard/values-si/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-si/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"යතුරු ආරක්ෂාව"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"PIN කේතය ටයිප් කරන්න"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM PUK සහ නව PIN කේතය ටයිප් කරන්න"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK කේතය"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"නව SIM PIN කේතය"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"මුරපදය ටයිප් කිරීමට ස්පර්ශ කරන්න"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"අගුළු ඇරීමට මුරපදය ටයිප් කරන්න"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"අගුළු හැරීමට PIN එක ටයිප් කරන්න"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"ඔබේ PIN ඇතුළු කරන්න"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"ඔබගේ රටාව ඇතුළු කරන්න"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"ඔබේ මුරපදය ඇතුළු කරන්න"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"වැරදි PIN කේතයකි."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"වලංගු නොවන කාඩ්පත."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"අරෝපිතයි"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • නොරැහැන්ව ආරෝපණ කෙරේ"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • වේගයෙන් ආරෝපණය වෙමින්"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • සෙමින් ආරෝපණය වෙමින්"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ආරෝපණය කිරීම තාවකාලිකව සීමා කර ඇත"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"ඔබගේ ආරෝපකයට සම්බන්ධ කරන්න."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"අගුලු හැරීමට මෙනුව ඔබන්න."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"ජාලය අගුළු දමා ඇත"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM පත නැත"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"උපාංග මුරපදය"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN කොටස"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK කොටස"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"<xliff:g id="ALARM">%1$s</xliff:g>ට ඊළඟ එලාමය සකසා ඇත"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"මකන්න"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM අබල කරන්න"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM අබල කළ නොහැකිය."</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"දෝෂයක් හේතුවෙන් eSIM අබල කළ නොහැකිය."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"ඇතුල් කරන්න"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"රටාව අමතකයි"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"වැරදි රටාවකි"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"වැරදි මුරපදයකි"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN එක වැරදියි"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">තත්පර <xliff:g id="NUMBER">%d</xliff:g>කින් නැවත උත්සාහ කරන්න.</item>
       <item quantity="other">තත්පර <xliff:g id="NUMBER">%d</xliff:g>කින් නැවත උත්සාහ කරන්න.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"ඔබගේ රටාව අඳින්න"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM PIN ඇතුළු කරන්න"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" සඳහා SIM PIN ඇතුළු කරන්න"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> ජංගම සේවාවෙන් තොරව උපාංගය භාවිත කිරීමට eSIM අබල කරන්න."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"PIN එක ඇතුළු කරන්න"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"මුරපදය ඇතුළු කරන්න"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"දැන් SIM එක අබල කර ඇත. ඉදිරියට යාමට PUK කේතය යොදන්න. විස්තර සඳහා වාහකයා අමතන්න."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" දැන් අබල කර ඇත. දිගටම පවත්වා ගෙන යාමට PUK කේතය ඇතුළත් කරන්න. විස්තර සඳහා වාහකයා සම්බන්ධ කර ගන්න."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"අපේක්ෂිත PIN කේතය ඇතුළත් කරන්න"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM පත අගුළු හරිමින්..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 සිට 8 දක්වා අංක සහිත PIN එකක් ටයිප් කරන්න."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK කේතය සංඛ්‍යා 8 ක් හෝ වැඩි විය යුතුය."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"නිවැරදි PUK කේතය නැවත ඇතුලත් කරන්න. නැවත නැවත උත්සාහ කිරීමෙන් SIM එක ස්ථිරවම අබල කරයි."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"රටා උත්සාහ කිරීම් වැඩිය"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"ඔබ PIN අංකය <xliff:g id="NUMBER_0">%1$d</xliff:g> වාරයක් වැරදියට ටයිප් කොට ඇත.\n\n තත්පර <xliff:g id="NUMBER_1">%2$d</xliff:g> ක් ඇතුළත නැවත උත්සාහ කරන්න."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"ඔබ මුරපදය වාර <xliff:g id="NUMBER_0">%1$d</xliff:g> ක් වැරදියට ටයිප්කොට ඇත. \n\nතත්පර <xliff:g id="NUMBER_1">%2$d</xliff:g> කින් නැවත උත්සහ කරන්න."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"ඔබ <xliff:g id="NUMBER_0">%1$d</xliff:g> වාරයක් අගුළු ඇරීමේ රටාව වැරදියට ඇඳ ඇත. \n\nතත්පර <xliff:g id="NUMBER_1">%2$d</xliff:g> ක් ඇතුළත නැවත උත්සාහ කරන්න."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN මෙහෙයුම අසාර්ථක විය!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK මෙහෙයුම අසාර්ථක විය!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"කේතය පිළිගැණුනි!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"සේවාව නැත."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ආදාන ක්‍රමය මාරු කිරීම"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"ගුවන් යානා ප්‍රකාරය"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"උපාංගය නැවත ආරම්භ වූ පසු රටාව අවශ්‍යයි"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"අමතර ආරක්ෂාව සඳහා රටාව අවශ්‍යයි"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"අමතර ආරක්ෂාව සඳහා PIN අංකය අවශ්‍යයි"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"අමතර ආරක්ෂාව සඳහා මුරපදය අවශ්‍යයි"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"ඔබ පැතිකඩවල් මාරු කරන විට රටාව අවශ්‍යයි"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"ඔබ පැතිකඩවල් මාරු කරන විට PIN අංකය අවශ්‍යයි"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"ඔබ පැතිකඩවල් මාරු කරන විට මුරපදය අවශ්‍යයි"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ඔබගේ පරිපාලක විසින් උපාංගය අගුළු දමා ඇත"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"උපාංගය හස්තීයව අගුලු දමන ලදී"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">උපාංගය පැය <xliff:g id="NUMBER_1">%d</xliff:g>ක් අගුලු හැර නැත. රටාව තහවුරු කරන්න.</item>
-      <item quantity="other">උපාංගය පැය <xliff:g id="NUMBER_1">%d</xliff:g>ක් අගුලු හැර නැත. රටාව තහවුරු කරන්න.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">උපාංගය පැය <xliff:g id="NUMBER_1">%d</xliff:g>ක් අගුලු හැර නැත. PIN අංකය තහවුරු කරන්න.</item>
-      <item quantity="other">උපාංගය පැය <xliff:g id="NUMBER_1">%d</xliff:g>ක් අගුලු හැර නැත. PIN අංකය තහවුරු කරන්න.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">උපාංගය පැය <xliff:g id="NUMBER_1">%d</xliff:g>ක් අගුලු හැර නැත. මුරපදය තහවුරු කරන්න.</item>
-      <item quantity="other">උපාංගය පැය <xliff:g id="NUMBER_1">%d</xliff:g>ක් අගුලු හැර නැත. මුරපදය තහවුරු කරන්න.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"හඳුනා නොගන්නා ලදී"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"හඳුනා නොගන්නා ලදී"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-sk/strings.xml b/packages/SystemUI/res-keyguard/values-sk/strings.xml
index 795eaba..5e4c248 100644
--- a/packages/SystemUI/res-keyguard/values-sk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sk/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Zámka klávesnice"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Zadajte kód PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Zadajte kód PUK SIM karty a nový kód PIN"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Kód PUK SIM karty"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nový kód PIN SIM karty"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Heslo zadajte po klepnutí"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Zadajte heslo na odomknutie"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Zadajte kód PIN na odomknutie"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Zadajte PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Zadajte vzor"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Zadajte heslo"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Nesprávny kód PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Neplatná karta."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Nabité"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa bezdrôtovo"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa rýchlo"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíja sa pomaly"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Nabíjanie je dočasne obmedzené"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Pripojte nabíjačku."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Odomknete stlačením tlačidla ponuky."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Sieť je zablokovaná"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Žiadna SIM karta"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Heslo zariadenia"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Oblasť kódu PIN SIM karty"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Oblasť kódu PUK SIM karty"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Nasledujúci budík je nastavený na <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Odstrániť"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Zakázať eSIM kartu"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM karta sa nedá deaktivovať"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM karta sa nedá deaktivovať, pretože sa vyskytla chyba."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Nepamätám si vzor"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Nesprávny vzor"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Nesprávne heslo"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Nesprávny kód PIN"</string>
@@ -70,12 +58,9 @@
       <item quantity="other">Skúste to znova o <xliff:g id="NUMBER">%d</xliff:g> sekúnd.</item>
       <item quantity="one">Skúste to znova o 1 sekundu.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Nakreslite svoj vzor"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Zadajte PIN pre SIM kartu"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Zadajte kód PIN pre SIM kartu operátora <xliff:g id="CARRIER">%1$s</xliff:g>."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Zakážte eSIM kartu a používajte zariadenie bez mobilnej služby."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Zadajte kód PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Zadajte heslo"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM karta je teraz zakázaná. Ak chcete pokračovať, zadajte kód PUK. Podrobné informácie získate od operátora."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM karta operátora <xliff:g id="CARRIER">%1$s</xliff:g> bola zakázaná. Ak chcete pokračovať, zadajte kód PUK. Podrobnosti získate od svojho operátora."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Zadajte požadovaný kód PIN"</string>
@@ -83,8 +68,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Prebieha odomykanie SIM karty…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Zadajte kód PIN s dĺžkou 4 až 8 číslic."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Kód PUK musí obsahovať 8 alebo viac číslic."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Znova zadajte správny kód PUK. Opakované pokusy zakážu SIM kartu natrvalo."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Príliš veľa pokusov o nakreslenie vzoru"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Už <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát ste zadali nesprávny kód PIN. \n\nSkúste to znova o <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Už <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát ste zadali nesprávne heslo. \n\nSkúste to znova o <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Už <xliff:g id="NUMBER_0">%1$d</xliff:g>-krát ste použili nesprávny bezpečnostný vzor. \n\nSkúste to znova o <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
@@ -104,8 +87,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Operácia kódu PIN SIM karty zlyhala!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Operácia kódu PUK SIM karty zlyhala!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kód bol prijatý."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Žiadny signál."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Prepnúť metódu vstupu"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Režim v lietadle"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Po reštartovaní zariadenia musíte zadať bezpečnostný vzor"</string>
@@ -114,29 +95,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Na ďalšie zabezpečenie musíte zadať bezpečnostný vzor"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Na ďalšie zabezpečenie musíte zadať kód PIN"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Na ďalšie zabezpečenie musíte zadať heslo"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Po prepnutí profilov musíte zadať bezpečnostný vzor"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Po prepnutí profilov musíte zadať kód PIN"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Po prepnutí profilov musíte zadať heslo"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Zariadenie zamkol správca"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Zariadenie bolo uzamknuté ručne"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="few">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_1">%d</xliff:g> hodiny. Potvrďte vzor.</item>
-      <item quantity="many">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_1">%d</xliff:g> hodiny. Potvrďte vzor.</item>
-      <item quantity="other">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_1">%d</xliff:g> hodín. Potvrďte vzor.</item>
-      <item quantity="one">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_0">%d</xliff:g> hodinu. Potvrďte vzor.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="few">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_1">%d</xliff:g> hodiny. Potvrďte kód PIN.</item>
-      <item quantity="many">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_1">%d</xliff:g> hodiny. Potvrďte kód PIN.</item>
-      <item quantity="other">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_1">%d</xliff:g> hodín. Potvrďte kód PIN.</item>
-      <item quantity="one">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_0">%d</xliff:g> hodinu. Potvrďte kód PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="few">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_1">%d</xliff:g> hodiny. Potvrďte heslo.</item>
-      <item quantity="many">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_1">%d</xliff:g> hodiny. Potvrďte heslo.</item>
-      <item quantity="other">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_1">%d</xliff:g> hodín. Potvrďte heslo.</item>
-      <item quantity="one">Zariadenie nebolo odomknuté <xliff:g id="NUMBER_0">%d</xliff:g> hodinu. Potvrďte heslo.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nerozpoznané"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nerozpoznané"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-sl/strings.xml b/packages/SystemUI/res-keyguard/values-sl/strings.xml
index bb388ea..149ac8e 100644
--- a/packages/SystemUI/res-keyguard/values-sl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sl/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Vnesite kodo PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Vnesite kodo PUK in novo kodo PIN kartice SIM"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Koda PUK kartice SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nova koda PIN kartice SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Dotaknite se za vnos gesla"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Vnesite geslo za odklepanje"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Vnesite kodo PIN za odklepanje"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Vnesite kodo PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Vnesite vzorec"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Vnesite geslo"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Napačna koda PIN."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Neveljavna kartica"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Baterija napolnjena"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • brezžično polnjenje"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • hitro polnjenje"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • počasno polnjenje"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Polnjenje začasno omejeno"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Priključite napajalnik."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Če želite odkleniti, pritisnite meni."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Omrežje je zaklenjeno"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Ni kartice SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Geslo naprave"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Območje za kodo PIN kartice SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Območje za kodo PUK kartice SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Naslednji alarm je nastavljen za <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Izbris"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Onemogoči kartico e-SIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Digitalne kartice e-SIM ni mogoče onemogočiti"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Digitalne kartice e-SIM zaradi napake ni mogoče onemogočiti."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Tipka Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Pozabljen vzorec"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Napačen vzorec"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Napačno geslo"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Napačna koda PIN"</string>
@@ -70,12 +58,9 @@
       <item quantity="few">Poskusite znova čez <xliff:g id="NUMBER">%d</xliff:g> sekunde.</item>
       <item quantity="other">Poskusite znova čez <xliff:g id="NUMBER">%d</xliff:g> sekund.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Narišite vzorec"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Vnesite kodo PIN kartice SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Vnesite kodo PIN kartice SIM operaterja »<xliff:g id="CARRIER">%1$s</xliff:g>«."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Onemogočite digitalno kartico e-SIM, če želite napravo uporabljati brez mobilne storitve."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Vnesite kodo PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Vnesite geslo"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Kartica SIM je onemogočena. Če želite nadaljevati, vnesite kodo PUK. Za dodatne informacije se obrnite na operaterja."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Kartica SIM operaterja »<xliff:g id="CARRIER">%1$s</xliff:g>« je onemogočena. Če želite nadaljevati, vnesite kodo PUK. Za podrobnosti se obrnite na operaterja."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Vnesite želeno kodo PIN"</string>
@@ -83,8 +68,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Odklepanje kartice SIM …"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Vnesite kodo PIN, ki vsebuje od štiri do osem številk."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Koda PUK mora biti 8- ali večmestno število."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Znova vnesite pravilno kodo PUK. Večkratni poskusi bodo trajno onemogočili kartico SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Preveč poskusov vnosa vzorca"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Kodo PIN ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat vnesli napačno. \n\nPoskusite znova čez <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Geslo ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat vnesli napačno. \n\nPoskusite znova čez <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Vzorec za odklepanje ste <xliff:g id="NUMBER_0">%1$d</xliff:g>-krat nepravilno narisali. \n\nPoskusite znova čez <xliff:g id="NUMBER_1">%2$d</xliff:g> s."</string>
@@ -104,8 +87,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Postopek za odklepanje s kodo PIN kartice SIM ni uspel."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Postopek za odklepanje s kodo PUK kartice SIM ni uspel."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Koda je sprejeta."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Ni storitve."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Preklop načina vnosa"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Način za letalo"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Po vnovičnem zagonu naprave je treba vnesti vzorec"</string>
@@ -114,29 +95,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Zaradi dodatne varnosti morate vnesti vzorec"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Zaradi dodatne varnosti morate vnesti kodo PIN"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Zaradi dodatne varnosti morate vnesti geslo"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Po preklopu profilov je treba vnesti vzorec"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Po preklopu profilov je treba vnesti kodo PIN"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Po preklopu profilov je treba vnesti geslo"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Napravo je zaklenil skrbnik"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Naprava je bila ročno zaklenjena"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> uro. Potrdite vzorec.</item>
-      <item quantity="two">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> uri. Potrdite vzorec.</item>
-      <item quantity="few">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> ure. Potrdite vzorec.</item>
-      <item quantity="other">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> ur. Potrdite vzorec.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> uro. Potrdite kodo PIN.</item>
-      <item quantity="two">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> uri. Potrdite kodo PIN.</item>
-      <item quantity="few">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> ure. Potrdite kodo PIN.</item>
-      <item quantity="other">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> ur. Potrdite kodo PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> uro. Potrdite geslo.</item>
-      <item quantity="two">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> uri. Potrdite geslo.</item>
-      <item quantity="few">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> ure. Potrdite geslo.</item>
-      <item quantity="other">Naprava ni bila odklenjena <xliff:g id="NUMBER_1">%d</xliff:g> ur. Potrdite geslo.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Ni prepoznano"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Ni prepoznano"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-sq/strings.xml b/packages/SystemUI/res-keyguard/values-sq/strings.xml
index 2aaeecf..5fca45b 100644
--- a/packages/SystemUI/res-keyguard/values-sq/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sq/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Mbrojtësi i tasteve"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Shkruaj kodin PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Shkruaj kodin e ri PUK dhe PIN të kartës SIM"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Kodi PUK i kartës SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Kodi i ri PIN i kartës SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Prek për të shkruar fjalëkalimin"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Shkruaj fjalëkalimin për të shkyçur"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Shkruaj kodin PIN për ta shkyçur"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Fut kodin PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Fut motivin"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Fut fjalëkalimin"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Kodi PIN është i pasaktë."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Karta e pavlefshme."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"I karikuar"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me valë"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet me shpejtësi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Po karikohet ngadalë"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Karikimi përkohësisht i kufizuar"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Lidh karikuesin."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Shtyp \"Meny\" për të shkyçur."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Rrjeti është i kyçur"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Nuk ka kartë SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Fjalëkalimi i pajisjes"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Zona PIN e kartës SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Zona e kodit PUK të kartës SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Alarmi tjetër i caktuar: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Fshi"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Çaktivizo kartën eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Karta eSIM nuk mund të çaktivizohet"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Karta eSIM nuk mund të çaktivizohet për shkak të një gabimi."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Dërgo"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Harrova motivin"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Motiv i gabuar"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Fjalëkalim i gabuar"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Kod PIN i gabuar"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Provo sërish për <xliff:g id="NUMBER">%d</xliff:g> sekonda.</item>
       <item quantity="one">Provo sërish për 1 sekondë.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Vizato motivin tënd"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Fut kodin PIN të kartës SIM"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Fut kodin PIN të kartës SIM për \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Çaktivizo kartën eSIM për ta përdorur pajisjen pa shërbimin celular."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Fut kodin PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Fut fjalëkalimin"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Karta SIM tani është e çaktivizuar. Fut kodin PUK për të vazhduar. Kontakto me operatorin për detaje."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Karta SIM e \"<xliff:g id="CARRIER">%1$s</xliff:g>\" tani është e çaktivizuar. Fut kodin PUK për të vazhduar. Kontakto me operatorin për detaje."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Fut kodin PIN të dëshiruar"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Po shkyç kartën SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Shkruaj një PIN me 4 deri në 8 numra."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Kodi PUK duhet të jetë me 8 numra ose më shumë."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Fut kodin e saktë PUK. Provat e përsëritura do ta çaktivizojnë përgjithmonë kartën SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Shumë tentativa për motivin"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"E ke shkruar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë gabimisht kodin PIN.\n\nProvo sërish për <xliff:g id="NUMBER_1">%2$d</xliff:g> sekonda."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"E ke shkruar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë gabimisht fjalëkalimin.\n\nProvo sërish për <xliff:g id="NUMBER_1">%2$d</xliff:g> sekonda."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Ke tentuar <xliff:g id="NUMBER_0">%1$d</xliff:g> herë pa sukses për të vizatuar motivin tënd. \n\nProvo sërish për <xliff:g id="NUMBER_1">%2$d</xliff:g> sekonda."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Operacioni i kodit PIN të kartës SIM dështoi!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Operacioni i kodit PUK të kartës SIM dështoi!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kodi u pranua!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Nuk ka shërbim."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Ndërro metodën e hyrjes"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Modaliteti i aeroplanit"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Kërkohet motivi pas rinisjes së pajisjes"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Kërkohet motivi për më shumë siguri"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Kërkohet kodi PIN për më shumë siguri"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Kërkohet fjalëkalimi për më shumë siguri"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Kërkohet motivi kur ndryshon profilet"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Kërkohet kodi PIN kur ndryshon profilet"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Kërkohet fjalëkalimi kur ndryshon profilet"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Pajisja është e kyçur nga administratori"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Pajisja është kyçur manualisht"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Pajisja nuk është shkyçur për <xliff:g id="NUMBER_1">%d</xliff:g> orë. Konfirmo motivin.</item>
-      <item quantity="one">Pajisja nuk është shkyçur për <xliff:g id="NUMBER_0">%d</xliff:g> orë. Konfirmo motivin.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Pajisja nuk është shkyçur për <xliff:g id="NUMBER_1">%d</xliff:g> orë. Konfirmo kodin PIN.</item>
-      <item quantity="one">Pajisja nuk është shkyçur për <xliff:g id="NUMBER_0">%d</xliff:g> orë. Konfirmo kodin PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Pajisja nuk është shkyçur për <xliff:g id="NUMBER_1">%d</xliff:g> orë. Konfirmo fjalëkalimin.</item>
-      <item quantity="one">Pajisja nuk është shkyçur për <xliff:g id="NUMBER_0">%d</xliff:g> orë. Konfirmo fjalëkalimin.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Nuk njihet"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Nuk njihet"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-sr/strings.xml b/packages/SystemUI/res-keyguard/values-sr/strings.xml
index 757f630..7facbfb 100644
--- a/packages/SystemUI/res-keyguard/values-sr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sr/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Закључавање тастатуре"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Унесите PIN кôд"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Унесите PUK за SIM и нови PIN кôд"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK кôд за SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Нови PIN кôд за SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Додирните за унос лозинке"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Унесите лозинку да бисте откључали"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Унесите PIN за откључавање"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Унесите PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Унесите шаблон"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Унесите лозинку"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN кôд је нетачан."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Неважећа картица."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Напуњена је"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бежично пуњење"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Брзо се пуни"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Споро се пуни"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Пуњење је привремено ограничено"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Прикључите пуњач."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Притисните Мени да бисте откључали."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мрежа је закључана"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Нема SIM картице"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Лозинка за уређај"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Област за PIN за SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Област за PUK за SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Следећи аларм је подешен за <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Избриши"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Онемогући eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Онемогућавање eSIM-а није успело"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"eSIM не може да се онемогући због грешке."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Заборавио/ла сам шаблон"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Погрешан шаблон"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Погрешна лозинка"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Погрешан PIN"</string>
@@ -69,12 +57,9 @@
       <item quantity="few">Пробајте поново за <xliff:g id="NUMBER">%d</xliff:g> секунде.</item>
       <item quantity="other">Пробајте поново за <xliff:g id="NUMBER">%d</xliff:g> секунди.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Нацртајте шаблон"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Унесите PIN за SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Унесите PIN за SIM „<xliff:g id="CARRIER">%1$s</xliff:g>“."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Онемогућите eSIM да бисте уређај користили без мобилне услуге."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Унесите PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Унесите лозинку"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM картица је сада онемогућена. Унесите PUK кôд да бисте наставили. Детаљне информације потражите од мобилног оператера."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM „<xliff:g id="CARRIER">%1$s</xliff:g>“ је сада онемогућен. Унесите PUK кôд да бисте наставили. Детаљне информације потражите од мобилног оператера."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Унесите жељени PIN кôд"</string>
@@ -82,8 +67,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM картица се откључава…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Унесите PIN који има 4–8 бројева."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK кôд треба да има 8 или више бројева."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Поново унесите тачан PUK кôд. Поновљени покушаји ће трајно онемогућити SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Превише покушаја уноса шаблона"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Унели сте погрешан PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Унели сте погрешну лозинку <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Нацртали сте нетачан шаблон за откључавање <xliff:g id="NUMBER_0">%1$d</xliff:g> пута. \n\nПробајте поново за <xliff:g id="NUMBER_1">%2$d</xliff:g> сек."</string>
@@ -101,8 +84,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Радња са PIN кодом за SIM није успела!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Радња са PUK кодом за SIM није успела!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Кôд је прихваћен!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Мрежа није доступна."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Промени метод уноса"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Режим рада у авиону"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Треба да унесете шаблон када се уређај поново покрене"</string>
@@ -111,26 +92,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Треба да унесете шаблон ради додатне безбедности"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Треба да унесете PIN ради додатне безбедности"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Треба да унесете лозинку ради додатне безбедности"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Треба да унесете шаблон када прелазите са једног профила на други"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Треба да унесете PIN када прелазите са једног профила на други"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Треба да унесете лозинку када прелазите са једног профила на други"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Администратор је закључао уређај"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Уређај је ручно закључан"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Нисте откључали уређај <xliff:g id="NUMBER_1">%d</xliff:g> сат. Потврдите шаблон.</item>
-      <item quantity="few">Нисте откључали уређај <xliff:g id="NUMBER_1">%d</xliff:g> сата. Потврдите шаблон.</item>
-      <item quantity="other">Нисте откључали уређај <xliff:g id="NUMBER_1">%d</xliff:g> сати. Потврдите шаблон.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Нисте откључали уређај <xliff:g id="NUMBER_1">%d</xliff:g> сат. Потврдите PIN.</item>
-      <item quantity="few">Нисте откључали уређај <xliff:g id="NUMBER_1">%d</xliff:g> сата. Потврдите PIN.</item>
-      <item quantity="other">Нисте откључали уређај <xliff:g id="NUMBER_1">%d</xliff:g> сати. Потврдите PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Нисте откључали уређај <xliff:g id="NUMBER_1">%d</xliff:g> сат. Потврдите лозинку.</item>
-      <item quantity="few">Нисте откључали уређај <xliff:g id="NUMBER_1">%d</xliff:g> сата. Потврдите лозинку.</item>
-      <item quantity="other">Нисте откључали уређај <xliff:g id="NUMBER_1">%d</xliff:g> сати. Потврдите лозинку.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Није препознат"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Није препознат"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-sv/strings.xml b/packages/SystemUI/res-keyguard/values-sv/strings.xml
index fb2571e..f271dda 100644
--- a/packages/SystemUI/res-keyguard/values-sv/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sv/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Ange pinkod"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Ange PUK-koden och en ny pinkod för SIM-kortet"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK-kod för SIM-kortet"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Ny pinkod för SIM-kortet"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Tryck om du vill ange lösenord"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Lås upp med lösenordet"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Lås upp med pinkoden"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Ange pinkoden"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Ange det grafiska lösenordet"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Ange ditt lösenord"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Fel pinkod."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ogiltigt kort."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Laddat"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas trådlöst"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas snabbt"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddas långsamt"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Laddning har begränsats tillfälligt"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Anslut laddaren."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Lås upp genom att trycka på Meny."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Nätverk låst"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Inget SIM-kort"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Lösenord för enhet"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Pinkodsområde för SIM-kort"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"PUK-kodsområde för SIM-kort"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Nästa alarm är inställt på <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Radera"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Inaktivera eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Det gick inte att inaktivera eSIM-kortet"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Det gick inte att inaktivera eSIM-kortet på grund av ett fel."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Retur"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Har du glömt ditt grafiska lösenord?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Fel mönster"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Fel lösenord"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Fel pinkod"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Försök igen om <xliff:g id="NUMBER">%d</xliff:g> sekunder.</item>
       <item quantity="one">Försök igen om 1 sekund.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Rita ditt grafiska lösenord"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Ange pinkod för SIM-kortet."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Ange pinkod för SIM-kortet för <xliff:g id="CARRIER">%1$s</xliff:g>."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Inaktivera eSIM om du vill använda enheten utan mobiltjänst."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Ange pinkod"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Ange lösenord"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM-kortet har inaktiverats. Du måste ange en PUK-kod innan du kan fortsätta. Kontakta operatören för mer information."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM-kortet för <xliff:g id="CARRIER">%1$s</xliff:g> har inaktiverats. Du måste ange en PUK-kod innan du kan fortsätta. Kontakta operatören för mer information."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Ange önskad pinkod"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Låser upp SIM-kort …"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Ange en pinkod med fyra till åtta siffror."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-koden ska vara minst åtta siffror."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Ange rätt PUK-kod. Om försöken upprepas inaktiveras SIM-kortet permanent."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"För många försök med mönster"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Du har angett fel pinkod <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. \n\nFörsök igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Du har angett fel lösenord <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. \n\nFörsök igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Du har ritat ditt grafiska lösenord fel <xliff:g id="NUMBER_0">%1$d</xliff:g> gånger. \n\nFörsök igen om <xliff:g id="NUMBER_1">%2$d</xliff:g> sekunder."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Det gick inte att låsa upp med pinkoden för SIM-kortet."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Det gick inte att låsa upp med PUK-koden för SIM-kortet."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Koden godkändes."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Ingen tjänst."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Byt inmatningsmetod"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Flygplansläge"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Du måste rita mönster när du har startat om enheten"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Du måste rita mönster för ytterligare säkerhet"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Du måste ange pinkod för ytterligare säkerhet"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Du måste ange lösenord för ytterligare säkerhet"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Du måste rita mönster när du byter profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Du måste ange pinkod när du byter profil"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Du måste ange lösenord när du byter profil"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Administratören har låst enheten"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Enheten har låsts manuellt"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Enheten har inte låsts upp på <xliff:g id="NUMBER_1">%d</xliff:g> timmar. Bekräfta det grafiska lösenordet.</item>
-      <item quantity="one">Enheten har inte låsts upp på <xliff:g id="NUMBER_0">%d</xliff:g> timme. Bekräfta det grafiska lösenordet.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Enheten har inte låsts upp på <xliff:g id="NUMBER_1">%d</xliff:g> timmar. Bekräfta pinkoden.</item>
-      <item quantity="one">Enheten har inte låsts upp på <xliff:g id="NUMBER_0">%d</xliff:g> timme. Bekräfta pinkoden.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Enheten har inte låsts upp på <xliff:g id="NUMBER_1">%d</xliff:g> timmar. Bekräfta lösenordet.</item>
-      <item quantity="one">Enheten har inte låsts upp på <xliff:g id="NUMBER_0">%d</xliff:g> timme. Bekräfta lösenordet.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Identifierades inte"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Identifierades inte"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-sw/strings.xml b/packages/SystemUI/res-keyguard/values-sw/strings.xml
index 5381d76..c84bef0 100644
--- a/packages/SystemUI/res-keyguard/values-sw/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-sw/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Kilinda vitufe"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Weka nambari ya PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Weka PUK na nambari mpya ya PIN ya SIM"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Nambari ya PUK ya SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Nambari mpya ya PIN ya SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Gusa ili uandike nenosiri"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Andika nenosiri ili ufungue"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Andika PIN ili ufungue"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Weka PIN yako"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Weka mchoro wako"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Weka nenosiri lako"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Nambari ya PIN si sahihi."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Kadi si Sahihi."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Betri imejaa"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji bila kutumia waya"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji kwa kasi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Inachaji pole pole"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kuchaji kumedhibitiwa kwa muda"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Unganisha chaja yako."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Bonyeza Menyu ili kufungua."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mtandao umefungwa"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Hakuna SIM kadi"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Nenosiri la kifaa"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Eneo la PIN ya SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Eneo la PUK ya SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Kengele inayofuata italia saa <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Futa"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Zima eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Imeshindwa kuzima eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Hitilafu imetokea wakati wa kuzima eSIM."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Weka"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Umesahau Mchoro"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Mchoro si sahihi"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Nenosiri si sahihi"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Nambari ya PIN si sahihi"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Jaribu tena baada ya sekunde <xliff:g id="NUMBER">%d</xliff:g>.</item>
       <item quantity="one">Jaribu tena baada ya sekunde 1.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Chora mchoro wako"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Weka PIN ya SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Weka PIN ya SIM ya \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Zima eSIM ili utumie kifaa bila huduma ya vifaa vya mkononi."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Weka PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Weka Nenosiri"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM sasa imefungwa. Weka nambari ya PUK ili uendelee. Wasiliana na mtoa huduma za mtandao kwa maelezo."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM ya \"<xliff:g id="CARRIER">%1$s</xliff:g>\" sasa imezimwa. Weka nambari ya PUK ili uendelee. Wasiliana na mtoa huduma kwa maelezo."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Weka nambari ya PIN unayopendelea"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Inafungua SIM kadi..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Andika PIN ya tarakimu 4 hadi 8."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Nambari ya PUK inafaa kuwa na tarakimu 8 au zaidi."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Weka tena nambari sahihi wa PUK. Ukirudia mara nyingi utafunga SIM kabisa."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Umejaribu kuchora mchoro mara nyingi mno"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Umeandika vibaya PIN mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Umeandika vibaya nenosiri lako mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Umechora vibaya mchoro wako wa kufungua mara <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Jaribu tena baada ya sekunde <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Utendakazi wa PIN ya SIM haujafanikiwa!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Utendakazi wa PUK ya SIM haujafanikiwa!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Nambari Imekubaliwa!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Hakuna mtandao."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Kubadili mbinu ya kuingiza data"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Hali ya ndegeni"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Unafaa kuchora mchoro baada ya kuwasha kifaa upya"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Mchoro unahitajika ili kuongeza usalama"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"PIN inahitajika ili kuongeza usalama"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Nenosiri linahitajika ili kuongeza usalama."</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Mchoro unahitajika unapobadili wasifu"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"PIN inahitajika unapobadili wasifu"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Nenosiri linahitajika unapobadili wasifu"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Msimamizi amefunga kifaa"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Umefunga kifaa mwenyewe"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Hujafungua kifaa kwa saa <xliff:g id="NUMBER_1">%d</xliff:g>. Thibitisha mchoro.</item>
-      <item quantity="one">Hujafungua kifaa kwa saa <xliff:g id="NUMBER_0">%d</xliff:g>. Thibitisha mchoro.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Hujafungua kifaa kwa saa <xliff:g id="NUMBER_1">%d</xliff:g>. Thibitisha PIN.</item>
-      <item quantity="one">Hujafungua kifaa kwa saa <xliff:g id="NUMBER_0">%d</xliff:g>. Thibitisha PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Hujafungua kifaa kwa saa <xliff:g id="NUMBER_1">%d</xliff:g>. Thibitisha nenosiri.</item>
-      <item quantity="one">Hujafungua kifaa kwa saa <xliff:g id="NUMBER_0">%d</xliff:g>. Thibitisha nenosiri.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Haitambuliwi"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Haitambuliwi"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml b/packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml
index e09bf7e..625ce1f 100644
--- a/packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml
+++ b/packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml
@@ -16,5 +16,7 @@
   -->
 
 <resources>
+    <!-- Allows PIN/Pattern to be drawn on one side of a display, and for the user to
+         switch sides -->
     <bool name="can_use_one_handed_bouncer">true</bool>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml b/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml
index e09bf7e..4daa648 100644
--- a/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml
+++ b/packages/SystemUI/res-keyguard/values-sw720dp/bools.xml
@@ -16,5 +16,11 @@
   -->
 
 <resources>
+    <!-- Allows PIN/Pattern to be drawn on one side of a display, and for the user to
+         switch sides -->
     <bool name="can_use_one_handed_bouncer">true</bool>
+
+    <!-- Will display the bouncer on one side of the display, and the current user icon and
+         user switcher on the other side -->
+    <bool name="bouncer_display_user_switcher">true</bool>
 </resources>
diff --git a/packages/SystemUI/res-keyguard/values-ta/strings.xml b/packages/SystemUI/res-keyguard/values-ta/strings.xml
index ef36fdd..151279e 100644
--- a/packages/SystemUI/res-keyguard/values-ta/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ta/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"பின் குறியீட்டை உள்ளிடவும்"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"சிம் PUK மற்றும் புதிய பின் குறியீட்டை உள்ளிடவும்"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"சிம் PUK குறியீடு"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"புதிய சிம் பின் குறியீடு"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"கடவுச்சொல்லை உள்ளிட, தொடவும்"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"அன்லாக் செய்ய கடவுச்சொல்லை உள்ளிடவும்"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"அன்லாக் செய்ய, பின்னை உள்ளிடவும்"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"பின்னை உள்ளிடுக"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"பேட்டர்னை உள்ளிடுக"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"கடவுச்சொல்லை உள்ளிடுக"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"தவறான பின் குறியீடு."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"செல்லாத சிம் கார்டு."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"சார்ஜ் செய்யப்பட்டது"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வயர்லெஸ் முறையில் சார்ஜாகிறது"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • வேகமாகச் சார்ஜாகிறது"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • மெதுவாகச் சார்ஜாகிறது"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • சார்ஜிங் தற்காலிகமாக வரம்பிடப்பட்டுள்ளது"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"சார்ஜரை இணைக்கவும்."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"அன்லாக் செய்ய மெனுவை அழுத்தவும்."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"நெட்வொர்க் பூட்டப்பட்டது"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"சிம் கார்டு இல்லை"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"சாதனத்தின் கடவுச்சொல்"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"சிம் பின்னுக்கான பகுதி"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"சிம் PUKக்கான பகுதி"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"அடுத்த அலாரம் <xliff:g id="ALARM">%1$s</xliff:g>க்கு அமைக்கப்பட்டுள்ளது"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"நீக்கும் பட்டன்"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"இ-சிம்மை முடக்கும்"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIMஐ முடக்க முடியவில்லை"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"பிழை ஏற்பட்டதால் eSIMஐ முடக்க முடியவில்லை."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"என்டர் பட்டன்"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"பேட்டர்ன் நினைவில்லையா"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"தவறான பேட்டர்ன்"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"தவறான கடவுச்சொல்"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"தவறான பின்"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> வினாடிகளுக்குப் பிறகு முயலவும்.</item>
       <item quantity="one">1 வினாடிக்குப் பிறகு முயலவும்.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"பேட்டர்னை வரையவும்"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"சிம் பின்னை உள்ளிடவும்."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\"க்கான சிம் பின்னை உள்ளிடவும்."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> மொபைல் சேவை இல்லாமல் சாதனத்தைப் பயன்படுத்த, eSIMஐ முடக்கவும்."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"பின்னை உள்ளிடவும்"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"கடவுச்சொல்லை உள்ளிடவும்"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர, PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு, தொலைத்தொடர்பு நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" சிம் தற்போது முடக்கப்பட்டுள்ளது. தொடர, PUK குறியீட்டை உள்ளிடவும். விவரங்களுக்கு, தொலைத்தொடர்பு நிறுவனத்தைத் தொடர்புகொள்ளவும்."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"பின் குறியீட்டை உள்ளிடவும்"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"சிம் கார்டைத் திறக்கிறது…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 இலிருந்து 8 எண்கள் உள்ள பின்னை உள்ளிடவும்."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK குறியீட்டில் 8 அல்லது அதற்கும் அதிகமான எண்கள் இருக்க வேண்டும்."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"சரியான PUK குறியீட்டை மீண்டும் உள்ளிடவும். தொடர் முயற்சிகள் சிம்மை நிரந்தரமாக முடக்கிவிடும்."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"பேட்டர்னை அதிக முறை தவறாக வரைந்துவிட்டீர்கள்"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"உங்கள் பின்னை <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக உள்ளிட்டுவிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"உங்கள் கடவுச்சொல்லை <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக உள்ளிட்டுவிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"அன்லாக் பேட்டர்னை, <xliff:g id="NUMBER_0">%1$d</xliff:g> முறை தவறாக வரைந்துவிட்டீர்கள். \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> வினாடிகளில் மீண்டும் முயலவும்."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"சிம் பின் செயல்பாடு தோல்வியடைந்தது!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"சிம் PUK செயல்பாடு தோல்வியடைந்தது!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"குறியீடு ஏற்கப்பட்டது!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"சேவை இல்லை."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"உள்ளீட்டு முறையை மாற்றும்"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"விமானப் பயன்முறை"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"சாதனத்தை மீண்டும் தொடங்கியதும், பேட்டர்னை வரைய வேண்டும்"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"கூடுதல் பாதுகாப்பிற்கு, பேட்டர்னை வரைய வேண்டும்"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"கூடுதல் பாதுகாப்பிற்கு, பின்னை உள்ளிட வேண்டும்"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"கூடுதல் பாதுகாப்பிற்கு, கடவுச்சொல்லை உள்ளிட வேண்டும்"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"சுயவிவரங்களுக்கு இடையே மாறும் போது, பேட்டர்னை வரைய வேண்டும்"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"சுயவிவரங்களுக்கு இடையே மாறும் போது, பின்னை உள்ளிட வேண்டும்"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"சுயவிவரங்களுக்கு இடையே மாறும் போது, கடவுச்சொல்லை உள்ளிட வேண்டும்"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"நிர்வாகி சாதனத்தைப் பூட்டியுள்ளார்"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"பயனர் சாதனத்தைப் பூட்டியுள்ளார்"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> மணிநேரமாகச் சாதனம் திறக்கப்படவில்லை. வடிவத்தை உறுதிப்படுத்தவும்.</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> மணிநேரமாகச் சாதனம் திறக்கப்படவில்லை. வடிவத்தை உறுதிப்படுத்தவும்.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> மணிநேரமாகச் சாதனம் திறக்கப்படவில்லை. பின்னை உறுதிப்படுத்தவும்.</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> மணிநேரமாகச் சாதனம் திறக்கப்படவில்லை. பின்னை உறுதிப்படுத்தவும்.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> மணிநேரமாகச் சாதனம் திறக்கப்படவில்லை. கடவுச்சொல்லை உறுதிப்படுத்தவும்.</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> மணிநேரமாகச் சாதனம் திறக்கப்படவில்லை. கடவுச்சொல்லை உறுதிப்படுத்தவும்.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"அடையாளங்காணபடவில்லை"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"அடையாளங்காணபடவில்லை"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index f9544af..30f3c83 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"కీగార్డ్"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"పిన్ కోడ్‌ను టైప్ చేయండి"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM PUK మరియు కొత్త పిన్ కోడ్‌ను టైప్ చేయండి"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK కోడ్"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"కొత్త SIM పిన్ కోడ్"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"పాస్‌వర్డ్‌ను టైప్ చేయడానికి తాకండి"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"అన్‌లాక్ చేయడానికి పాస్‌వర్డ్‌ను టైప్ చేయండి"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"అన్‌లాక్ చేయడానికి పిన్ టైప్ చేయండి"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"మీ పిన్‌ని నమోదు చేయండి"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"మీ నమూనాను నమోదు చేయండి"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"మీ పాస్‌వర్డ్‌ను నమోదు చేయండి"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"పిన్ కోడ్ తప్పు."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"చెల్లని కార్డ్."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"ఛార్జ్ చేయబడింది"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వైర్‌ లేకుండా ఛార్జ్ అవుతోంది"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • వేగంగా ఛార్జ్ అవుతోంది"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • నెమ్మదిగా ఛార్జ్ అవుతోంది"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • ఛార్జింగ్ తాత్కాలికంగా పరిమితం చేయబడింది"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"మీ ఛార్జర్‌ను కనెక్ట్ చేయండి."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"అన్‌లాక్ చేయడానికి మెనూను నొక్కండి."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"నెట్‌వర్క్ లాక్ చేయబడింది"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM కార్డ్ లేదు"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"పరికరం పాస్‌వర్డ్‌"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM పిన్ ప్రాంతం"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK ప్రాంతం"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"తర్వాత అలారం <xliff:g id="ALARM">%1$s</xliff:g>కి సెట్ చేయబడింది"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"తొలగించు"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIMని నిలిపివేయండి"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIMని నిలపడం సాధ్యపడదు"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"ఎర్రర్ కారణంగా eSIMని నిలపడం సాధ్యపడదు."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"నమూనాను మర్చిపోయాను"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"నమూనా తప్పు"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"పాస్‌వర్డ్ తప్పు"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"పిన్ తప్పు"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి.</item>
       <item quantity="one">1 సెకనులో మళ్లీ ప్రయత్నించండి.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"మీ నమూనాను గీయండి"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM పిన్‌ని నమోదు చేయండి."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" కోసం SIM పిన్‌ని నమోదు చేయండి."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> మొబైల్ సేవ లేకుండా పరికరాన్ని ఉపయోగించడం కోసం eSIMని నిలిపివేయండి."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"పిన్‌ను నమోదు చేయండి"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"పాస్‌వర్డ్‌ని నమోదు చేయండి"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"ఇప్పుడు SIM నిలిపివేయబడింది. కొనసాగించాలంటే, PUK కోడ్‌ను నమోదు చేయండి. వివరాల కోసం క్యారియర్‌ను సంప్రదించండి."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"ఇప్పుడు SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"ని నిలిపివేయడం జరిగింది. కొనసాగించాలంటే, PUK కోడ్‌ను నమోదు చేయండి. వివరాల కోసం క్యారియర్‌ను సంప్రదించండి."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"కావల్సిన పిన్ కోడ్‌ను నమోదు చేయండి"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM కార్డ్‌ని అన్‌లాక్ చేస్తోంది…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 నుండి 8 సంఖ్యలు ఉండే పిన్‌ను టైప్ చేయండి."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK కోడ్ అనేది 8 లేదా అంతకంటే ఎక్కువ సంఖ్యలు ఉండాలి."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"సరైన PUK కోడ్‌ను మళ్లీ నమోదు చేయండి. ఎక్కువసార్లు ప్రయత్నించడం వలన SIM శాశ్వతంగా నిలిపివేయబడుతుంది."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"నమూనాని చాలా ఎక్కువసార్లు గీసారు"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"మీరు మీ పిన్‌ను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా టైప్ చేశారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"మీరు మీ పాస్‌వర్డ్‌ను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా టైప్ చేశారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM పిన్ చర్య విఫలమైంది!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK చర్య విఫలమైంది!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"కోడ్ ఆమోదించబడింది!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"సేవ లేదు."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"ఇన్‌పుట్ పద్ధతిని మార్చు"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"విమానం మోడ్"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"పరికరాన్ని పునఃప్రారంభించిన తర్వాత నమూనాను గీయాలి"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"అదనపు భద్రత కోసం నమూనాని గీయాలి"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"అదనపు భద్రత కోసం పిన్ నమోదు చేయాలి"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"అదనపు భద్రత కోసం పాస్‌వర్డ్‌ని నమోదు చేయాలి"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"మీరు ప్రొఫైల్‌లను మార్చినప్పుడు నమూనాని గీయాలి"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"మీరు ప్రొఫైల్‌లను మార్చినప్పుడు పిన్‌ను నమోదు చేయాలి"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"మీరు ప్రొఫైల్‌లను మార్చినప్పుడు పాస్‌వర్డ్‌ని నమోదు చేయాలి"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"పరికరం నిర్వాహకుల ద్వారా లాక్ చేయబడింది"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"పరికరం మాన్యువల్‌గా లాక్ చేయబడింది"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> గంటల పాటు పరికరాన్ని అన్‌లాక్ చేయలేదు. నమూనాను గీయండి.</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> గంట పాటు పరికరాన్ని అన్‌లాక్ చేయలేదు. నమూనాను గీయండి.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> గంటల పాటు డివైజ్‌ను అన్‌లాక్ చేయలేదు. పిన్‌ను నిర్ధారించండి.</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> గంట పాటు డివైజ్‌ను అన్‌లాక్ చేయలేదు. పిన్‌ను నిర్ధారించండి.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other"><xliff:g id="NUMBER_1">%d</xliff:g> గంటల పాటు పరికరాన్ని అన్‌లాక్ చేయలేదు. పాస్‌వర్డ్‌ని నమోదు చేయండి.</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%d</xliff:g> గంట పాటు పరికరాన్ని అన్‌లాక్ చేయలేదు. పాస్‌వర్డ్‌ని నమోదు చేయండి.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"గుర్తించలేదు"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"గుర్తించలేదు"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-th/strings.xml b/packages/SystemUI/res-keyguard/values-th/strings.xml
index b0774c2..25968b7 100644
--- a/packages/SystemUI/res-keyguard/values-th/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-th/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"การล็อกปุ่มกด"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"พิมพ์รหัส PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"พิมพ์ PUK ของซิมและรหัส PIN ใหม่"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"รหัส PUK ของซิม"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"รหัส PIN ใหม่ของซิม"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"แตะเพื่อพิมพ์รหัสผ่าน"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"พิมพ์รหัสผ่านเพื่อปลดล็อก"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"พิมพ์ PIN เพื่อปลดล็อก"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"ป้อน PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"ป้อนรูปแบบ"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"ป้อนรหัสผ่าน"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"รหัส PIN ไม่ถูกต้อง"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"การ์ดไม่ถูกต้อง"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"ชาร์จแล้ว"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จแบบไร้สาย"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างเร็ว"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • กำลังชาร์จอย่างช้าๆ"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • จำกัดการชาร์จชั่วคราว"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"เสียบที่ชาร์จของคุณ"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"กด \"เมนู\" เพื่อปลดล็อก"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"เครือข่ายถูกล็อก"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"ไม่มีซิมการ์ด"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"รหัสผ่านของอุปกรณ์"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"พื้นที่ PIN ของซิม"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"พื้นที่ PUK ของซิม"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"ตั้งเวลาปลุกครั้งถัดไปไว้ที่ <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"ลบ"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"ปิดใช้ eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"ปิดใช้ eSIM ไม่ได้"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"ปิดใช้ eSIM ไม่ได้เนื่องจากมีข้อผิดพลาด"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"ลืมรูปแบบ"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"รูปแบบไม่ถูกต้อง"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"รหัสผ่านไม่ถูกต้อง"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN ไม่ถูกต้อง"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">ลองอีกครั้งใน <xliff:g id="NUMBER">%d</xliff:g> วินาที</item>
       <item quantity="one">ลองอีกครั้งใน 1 วินาที</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"ลากรูปแบบของคุณ"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"ป้อน PIN ของซิม"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"ป้อน PIN ของซิมสำหรับ \"<xliff:g id="CARRIER">%1$s</xliff:g>\""</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> ปิดใช้ eSIM เพื่อใช้อุปกรณ์โดยไม่มีบริการมือถือ"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"ป้อน PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"ป้อนรหัสผ่าน"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"ซิมการ์ดถูกปิดใช้แล้ว ป้อนรหัส PUK เพื่อดำเนินการต่อ โปรดสอบถามรายละเอียดจากผู้ให้บริการ"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"ปิดใช้ซิม \"<xliff:g id="CARRIER">%1$s</xliff:g>\" แล้ว ป้อนรหัส PUK เพื่อดำเนินการต่อ โปรดสอบถามรายละเอียดจากผู้ให้บริการ"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"ป้อนรหัส PIN ที่ต้องการ"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"กำลังปลดล็อกซิมการ์ด…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"พิมพ์ PIN ซึ่งเป็นเลข 4-8 หลัก"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"รหัส PUK ต้องเป็นตัวเลขอย่างน้อย 8 หลัก"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"ใส่รหัส PUK ที่ถูกต้องอีกครั้ง การพยายามซ้ำหลายครั้งจะทำให้ซิมการ์ดถูกปิดใช้งานอย่างถาวร"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"ลองหลายรูปแบบมากเกินไป"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"คุณพิมพ์ PIN ไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งใน <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"คุณพิมพ์รหัสผ่านไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งใน <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"คุณวาดรูปแบบการปลดล็อกไม่ถูกต้อง <xliff:g id="NUMBER_0">%1$d</xliff:g> ครั้งแล้ว \n\nโปรดลองอีกครั้งในอีก <xliff:g id="NUMBER_1">%2$d</xliff:g> วินาที"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"การปลดล็อกด้วย PIN ของซิมล้มเหลว!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"การปลดล็อกด้วย PUK ของซิมล้มเหลว!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"ระบบยอมรับรหัสแล้ว!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"ไม่มีบริการ"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"สลับวิธีการป้อนข้อมูล"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"โหมดบนเครื่องบิน"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"ต้องวาดรูปแบบหลังจากอุปกรณ์รีสตาร์ท"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"ต้องวาดรูปแบบเพื่อความปลอดภัยเพิ่มเติม"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"ต้องระบุ PIN เพื่อความปลอดภัยเพิ่มเติม"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"ต้องป้อนรหัสผ่านเพื่อความปลอดภัยเพิ่มเติม"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"ต้องวาดรูปแบบเมื่อคุณเปลี่ยนโปรไฟล์"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"ต้องระบุ PIN เมื่อคุณเปลี่ยนโปรไฟล์"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"ต้องป้อนรหัสผ่านเมื่อคุณเปลี่ยนโปรไฟล์"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"ผู้ดูแลระบบล็อกอุปกรณ์"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"มีการล็อกอุปกรณ์ด้วยตัวเอง"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_1">%d</xliff:g> ชั่วโมงแล้ว ยืนยันรูปแบบ</item>
-      <item quantity="one">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_0">%d</xliff:g> ชั่วโมงแล้ว ยืนยันรูปแบบ</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_1">%d</xliff:g> ชั่วโมงแล้ว ยืนยัน PIN</item>
-      <item quantity="one">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_0">%d</xliff:g> ชั่วโมงแล้ว ยืนยัน PIN</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_1">%d</xliff:g> ชั่วโมงแล้ว ยืนยันรหัสผ่าน</item>
-      <item quantity="one">ไม่มีการปลดล็อกอุปกรณ์มา <xliff:g id="NUMBER_0">%d</xliff:g> ชั่วโมงแล้ว ยืนยันรหัสผ่าน</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"ไม่รู้จัก"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"ไม่รู้จัก"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-tl/strings.xml b/packages/SystemUI/res-keyguard/values-tl/strings.xml
index a342e9c..8927c9e 100644
--- a/packages/SystemUI/res-keyguard/values-tl/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tl/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"I-type ang PIN code"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"I-type ang PUK ng SIM at ang bagong PIN code"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK code ng SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Bagong PIN code ng SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Pindutin para i-type password"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"I-type ang password upang i-unlock"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"I-type ang PIN upang i-unlock"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Ilagay ang iyong PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Ilagay ang iyong pattern"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Ilagay ang iyong password"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Mali ang PIN code."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Di-wasto ang Card."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Tapos nang mag-charge"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Wireless na nagcha-charge"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabilis na nagcha-charge"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Mabagal na nagcha-charge"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Pansamantalang limitado ang pag-charge"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Ikonekta ang iyong charger."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Pindutin ang Menu upang i-unlock."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Naka-lock ang network"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Walang SIM card"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Password ng device"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Lugar ng PIN ng SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Lugar ng PUK ng SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Nakatakda ang susunod na alarm nang <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"I-delete"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"I-disable ang eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Hindi ma-disable ang eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Hindi ma-disable ang eSIM dahil sa isang error."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Nakalimutan ang Pattern"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Mali ang pattern"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Mali ang password"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Mali ang PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">Subukang muli sa loob ng <xliff:g id="NUMBER">%d</xliff:g> segundo.</item>
       <item quantity="other">Subukang muli sa loob ng <xliff:g id="NUMBER">%d</xliff:g> na segundo.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Iguhit ang iyong pattern"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Ilagay ang PIN ng SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Ilagay ang PIN ng SIM para sa \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> I-disable ang eSIM upang magamit ang device nang walang serbisyo sa mobile."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Ilagay ang PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Ilagay ang Password"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Naka-disable na ngayon ang SIM. Ilagay ang PUK code upang magpatuloy. Makipag-ugnayan sa carrier para sa mga detalye."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"Naka-disable na ngayon ang SIM na \"<xliff:g id="CARRIER">%1$s</xliff:g>.\" Ilagay ang PUK code upang magpatuloy. Makipag-ugnayan sa carrier para sa mga detalye."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Ilagay ang gustong PIN code"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Ina-unlock ang SIM card…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Mag-type ng PIN na 4 hanggang 8 numero."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Dapat ay 8 numero o higit pa ang PUK code."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Muling ilagay ang tamang PUK code. Permanenteng madi-disable ang SIM dahil sa paulit-ulit na pagsubok."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Masyadong maraming pagsubok sa pattern"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Na-type mo nang mali ang iyong PIN nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. \n\nSubukang muli sa loob ng <xliff:g id="NUMBER_1">%2$d</xliff:g> (na) segundo."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Na-type mo nang hindi tama ang iyong password nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. \n\nSubukang muli sa loob ng <xliff:g id="NUMBER_1">%2$d</xliff:g> (na) segundo."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Naguhit mo nang hindi tama ang iyong pattern sa pag-unlock nang <xliff:g id="NUMBER_0">%1$d</xliff:g> (na) beses. \n\nSubukang muli sa loob ng <xliff:g id="NUMBER_1">%2$d</xliff:g> (na) segundo."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Nabigo ang operasyon ng PIN ng SIM!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Nabigo ang operasyon ng PUK ng SIM!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Tinanggap ang Code!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Walang serbisyo."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Magpalit ng pamamaraan ng pag-input"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Airplane mode"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Kailangan ng pattern pagkatapos mag-restart ng device"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Kinakailangan ang pattern para sa karagdagang seguridad"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Kinakailangan ang PIN para sa karagdagang seguridad"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Kinakailangan ang password para sa karagdagang seguridad"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Kinakailangan ang pattern kapag nagpalit ka ng profile"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Kinakailangan ang PIN kapag nagpalit ka ng profile"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Kinakailangan ang password kapag nagpalit ka ng profile"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Na-lock ng admin ang device"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Manual na na-lock ang device"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Hindi na-unlock ang device sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> oras. Kumpirmahin ang pattern.</item>
-      <item quantity="other">Hindi na-unlock ang device sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> na oras. Kumpirmahin ang pattern.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Hindi na-unlock ang device sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> oras. Kumpirmahin ang PIN.</item>
-      <item quantity="other">Hindi na-unlock ang device sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> na oras. Kumpirmahin ang PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Hindi na-unlock ang device sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> oras. Kumpirmahin ang password.</item>
-      <item quantity="other">Hindi na-unlock ang device sa loob ng <xliff:g id="NUMBER_1">%d</xliff:g> na oras. Kumpirmahin ang password.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Hindi nakilala"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Hindi nakilala"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-tr/strings.xml b/packages/SystemUI/res-keyguard/values-tr/strings.xml
index c10400b..5ba351a 100644
--- a/packages/SystemUI/res-keyguard/values-tr/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-tr/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"PIN kodunu yazın"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM PUK kodunu ve yeni bir PIN kodu yazın."</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM PUK kodu"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Yeni SIM PIN kodu"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Şifre yazmak için dokunun"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Kilidi açmak için şifreyi yazın"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Kilidi açmak için PIN kodunu yazın"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"PIN kodunuzu girin"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Deseninizi girin"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Şifrenizi girin"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Yanlış PIN kodu."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Geçersiz Kart."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Şarj oldu"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Kablosuz olarak şarj ediliyor"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Hızlı şarj oluyor"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Yavaş şarj oluyor"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Şarj etme geçici olarak sınırlı"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Şarj cihazınızı takın."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Kilidi açmak için Menü\'ye basın."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Ağ kilitli"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM kart yok"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Cihaz şifresi"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM PIN alanı"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM PUK alanı"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Sonraki alarm <xliff:g id="ALARM">%1$s</xliff:g> olarak ayarlandı"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Delete"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIM\'i devre dışı bırak"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM devre dışı bırakılamıyor"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Bir hata nedeniyle eSIM devre dışı bırakılamıyor."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Deseni unuttunuz mu?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Yanlış desen"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Yanlış şifre"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Yanlış PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> saniye içinde tekrar deneyin.</item>
       <item quantity="one">1 saniye içinde tekrar deneyin.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Deseninizi çizin"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM PIN kodunu girin."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"\"<xliff:g id="CARRIER">%1$s</xliff:g>\" için SIM PIN kodunu girin."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Cihazı mobil hizmet olmadan kullanmak için eSIM\'i devre dışı bırakın."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"PIN\'i girin"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Şifreyi Girin"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM kart artık devre dışı bırakıldı. Devam etmek için PUK kodunu girin. Ayrıntılı bilgi için operatörle bağlantı kurun."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"\"<xliff:g id="CARRIER">%1$s</xliff:g>1 SIM artık devre dışı. Devam etmek için PUK kodunu girin. Ayrıntılar için operatör ile iletişim kurun."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"İstenen PIN kodunu girin"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM kart kilidi açılıyor…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4 ila 8 haneli bir PIN yazın."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kodu 8 veya daha çok basamaklı bir sayı olmalıdır."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Doğru PUK kodunu tekrar girin. Çok sayıda deneme yapılırsa SIM kart kalıcı olarak devre dışı bırakılır."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Çok fazla sayıda desen denemesi yapıldı"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN kodunuzu <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış girdiniz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniye içinde tekrar deneyin."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Şifrenizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış yazdınız. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniye içinde tekrar deneyin."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Kilit açma deseninizi <xliff:g id="NUMBER_0">%1$d</xliff:g> kez yanlış çizdiniz. \n\n<xliff:g id="NUMBER_1">%2$d</xliff:g> saniye içinde tekrar deneyin."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM PIN işlemi başarısız oldu!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM PUK işlemi başarısız oldu!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kod Kabul Edildi!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Hizmet yok."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Giriş yöntemini değiştir"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Uçak modu"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Cihaz yeniden başladıktan sonra desen gerekir"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Ek güvenlik için desen gerekir"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Ek güvenlik için PIN gerekir"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Ek güvenlik için şifre gerekir"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Profil değiştirdiğinizde desen gerekir"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Profil değiştirdiğinizde PIN gerekir"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Profil değiştirdiğinizde şifre gerekir"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Cihaz, yönetici tarafından kilitlendi"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Cihazın manuel olarak kilitlendi"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Cihazın kilidi son <xliff:g id="NUMBER_1">%d</xliff:g> saattir açılmadı. Deseni doğrulayın.</item>
-      <item quantity="one">Cihazın kilidi son <xliff:g id="NUMBER_0">%d</xliff:g> saattir açılmadı. Deseni doğrulayın.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Cihazın kilidi son <xliff:g id="NUMBER_1">%d</xliff:g> saattir açılmadı. PIN\'i doğrulayın.</item>
-      <item quantity="one">Cihazın kilidi son <xliff:g id="NUMBER_0">%d</xliff:g> saattir açılmadı. PIN\'i doğrulayın.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Cihazın kilidi son <xliff:g id="NUMBER_1">%d</xliff:g> saattir açılmadı. Şifreyi doğrulayın.</item>
-      <item quantity="one">Cihazın kilidi son <xliff:g id="NUMBER_0">%d</xliff:g> saattir açılmadı. Şifreyi doğrulayın.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Tanınmadı"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Tanınmadı"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-uk/strings.xml b/packages/SystemUI/res-keyguard/values-uk/strings.xml
index 88a4d024..96f2ea2 100644
--- a/packages/SystemUI/res-keyguard/values-uk/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uk/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Введіть PIN-код"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Введіть PUK-код і новий PIN-код SIM-карти"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"PUK-код SIM-карти"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Новий PIN-код SIM-карти"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Торкніться, щоб ввести пароль"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Введіть пароль, щоб розблокувати"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Введіть PIN-код, щоб розблокувати"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Введіть PIN-код"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Введіть ключ"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Введіть пароль"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Неправильний PIN-код."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Недійсна картка."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Заряджено"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Бездротове заряджання"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Швидке заряджання"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Повільне заряджання"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Заряджання тимчасово обмежено"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Підключіть зарядний пристрій."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Натисніть меню, щоб розблокувати."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Мережу заблоковано"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Немає SIM-карти"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Пароль пристрою"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"PIN-код SIM-карти"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"PUK-код SIM-карти"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Наступний сигнал: <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Видалити"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Вимкнути eSIM-карту"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Не вдається вимкнути eSIM-карту"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Не вдається вимкнути eSIM-карту через помилку."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Ввести"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Не пам’ятаю ключ"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Неправильний ключ"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Неправильний пароль"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Неправильний PIN-код"</string>
@@ -70,12 +58,9 @@
       <item quantity="many">Повторіть спробу через <xliff:g id="NUMBER">%d</xliff:g> секунд.</item>
       <item quantity="other">Повторіть спробу через <xliff:g id="NUMBER">%d</xliff:g> секунди.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Намалюйте ключ"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Введіть PIN-код SIM-карти."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Введіть PIN-код SIM-карти для оператора \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Вимкніть eSIM-карту, щоб використовувати пристрій без мобільного зв’язку."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Введіть PIN-код"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Введіть пароль"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"Зараз SIM-карту вимкнено. Введіть PUK-код, щоб продовжити. Зв’яжіться з оператором, щоб дізнатися більше."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM-карту \"<xliff:g id="CARRIER">%1$s</xliff:g>\" вимкнено. Щоб продовжити, введіть PUK-код. Щоб дізнатися більше, зв’яжіться з оператором."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Введіть потрібний PIN-код"</string>
@@ -83,8 +68,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Розблокування SIM-карти…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Введіть PIN-код із 4–8 цифр."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK-код має складатися зі щонайменше 8 цифр."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Повторно введіть правильний PUK-код. Численні спроби назавжди вимкнуть SIM-карту."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Забагато спроб намалювати ключ"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN-код неправильно введено стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПовторіть спробу через <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Пароль неправильно введено стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПовторіть спробу через <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Ключ розблокування неправильно намальовано стільки разів: <xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nПовторіть спробу через <xliff:g id="NUMBER_1">%2$d</xliff:g> с."</string>
@@ -104,8 +87,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Помилка введення PIN-коду SIM-карти."</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Помилка введення PUK-коду SIM-карти."</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Код прийнято."</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Зв’язку немає."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Змінити метод введення"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Режим польоту"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Після перезавантаження пристрою потрібно ввести ключ"</string>
@@ -114,29 +95,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Для додаткового захисту потрібно ввести ключ"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Для додаткового захисту потрібно ввести PIN-код"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Для додаткового захисту потрібно ввести пароль"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Під час переходу в інший профіль потрібно ввести ключ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Під час переходу в інший профіль потрібно ввести PIN-код"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Під час переходу в інший профіль потрібно ввести пароль"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Адміністратор заблокував пристрій"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Пристрій заблоковано вручну"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> годину. Підтвердьте ключ.</item>
-      <item quantity="few">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> години. Підтвердьте ключ.</item>
-      <item quantity="many">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> годин. Підтвердьте ключ.</item>
-      <item quantity="other">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> години. Підтвердьте ключ.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> годину. Підтвердьте PIN-код.</item>
-      <item quantity="few">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> години. Підтвердьте PIN-код.</item>
-      <item quantity="many">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> годин. Підтвердьте PIN-код.</item>
-      <item quantity="other">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> години. Підтвердьте PIN-код.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> годину. Підтвердьте пароль.</item>
-      <item quantity="few">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> години. Підтвердьте пароль.</item>
-      <item quantity="many">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> годин. Підтвердьте пароль.</item>
-      <item quantity="other">Ви не розблоковували пристрій <xliff:g id="NUMBER_1">%d</xliff:g> години. Підтвердьте пароль.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Не розпізнано"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Не розпізнано"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-ur/strings.xml b/packages/SystemUI/res-keyguard/values-ur/strings.xml
index 96c7c1a..3ae43f9 100644
--- a/packages/SystemUI/res-keyguard/values-ur/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ur/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"کی گارڈ"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"‏PIN کوڈ ٹائپ کریں"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"‏SIM PUK اور نیا PIN کوڈ ٹائپ کریں"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"‏SIM PUK کوڈ"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"‏نیا SIM PIN کوڈ"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"پاس ورڈ ٹائپ کرنے کیلئے ٹچ کریں"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"غیر مقفل کرنے کیلئے پاس ورڈ ٹائپ کریں"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"‏غیر مقفل کرنے کیلئے PIN ٹائپ کریں"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"‏اپنا PIN درج کریں"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"اپنا پیٹرن درج کریں"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"اپنا پاس ورڈ درج کریں"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"‏غلط PIN کوڈ۔"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"غلط کارڈ۔"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"چارج ہوگئی"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • وائرلیس طریقے سے چارج ہو رہا ہے"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • تیزی سے چارج ہو رہا ہے"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • آہستہ چارج ہو رہا ہے"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • چارجنگ عارضی طور پر محدود ہے"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"اپنا چارجر منسلک کریں۔"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"غیر مقفل کرنے کیلئے مینو دبائیں۔"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"نیٹ ورک مقفل ہو گیا"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"‏کوئی SIM کارڈ نہیں ہے"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"آلے کا پاس ورڈ"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"‏SIM PIN کا علاقہ"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"‏SIM PUK کا علاقہ"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"اگلا الارم <xliff:g id="ALARM">%1$s</xliff:g> کیلئے سیٹ ہے"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"حذف کریں"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"‏eSIM غیر فعال کریں"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"‏eSIM کو غیر فعال نہیں کیا جا سکتا"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"‏ایک خرابی کی وجہ سے eSIM کو غیر فعال نہیں کیا جا سکتا۔"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"درج کریں"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"پیٹرن بھول گئے"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"غلط پیٹرن"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"غلط پاس ورڈ"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"‏غلط PIN"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> سیکنڈز میں دوبارہ کوشش کریں۔</item>
       <item quantity="one">1 سیکنڈ میں دوبارہ کوشش کریں۔</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"اپنا پیٹرن ڈرا کریں"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"‏SIM PIN درج کریں۔"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"‏\"<xliff:g id="CARRIER">%1$s</xliff:g>\" کیلئے SIM PIN درج کریں۔"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"‏<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> موبائل سروس کے بغیر آلہ کا استعمال کرنے کیلئے eSIM غیر فعال کریں۔"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"‏‫PIN درج کریں"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"پاس ورڈ درج کریں"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"‏SIM اب غیر فعال ہوگیا ہے۔ جاری رکھنے کیلئے PUK کوڈ درج کریں۔ تفصیلات کیلئے کیریئر سے رابطہ کریں۔"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"‏SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" اب غیر فعال ہے۔ جاری رکھنے کیلئے PUK کوڈ درج کریں۔ تفصیلات کیلئے کیریئر سے رابطہ کریں۔"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"‏پسندیدہ PIN کوڈ درج کریں"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"‏SIM کارڈ غیر مقفل ہو رہا ہے…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"‏ایسا PIN ٹائپ کریں جو 4 تا 8 اعداد پر مشتمل ہو۔"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"‏PUK کوڈ 8 یا زائد اعداد پر مشتمل ہونا چاہیے۔"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"‏صحیح PUK کوڈ دوبارہ درج کریں۔ بار بار کی کوششیں SIM کو مستقل طور پر غیر فعال کر دیں گی۔"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"پیٹرن کی بہت ساری کوششیں"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"‏آپ نے اپنا PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ٹائپ کیا ہے۔ \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"آپ نے اپنا پاس ورڈ <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ٹائپ کیا ہے۔ \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"آپ نے اپنا غیر مقفل کرنے کا پیٹرن <xliff:g id="NUMBER_0">%1$d</xliff:g> بار غلط طریقے سے ڈرا کیا ہے۔ \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> سیکنڈ میں دوبارہ کوشش کریں۔"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"‏SIM PIN کی کارروائی ناکام ہوگئی!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"‏SIM PUK کارروائی ناکام ہو گئی!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"کوڈ قبول کر لیا گیا!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"کوئی سروس نہیں ہے۔"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"اندراج کا طریقہ سوئچ کریں"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"ہوائی جہاز وضع"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"آلہ دوبارہ چالو ہونے کے بعد پیٹرن درکار ہوتا ہے"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"اضافی سیکیورٹی کیلئے پیٹرن درکار ہے"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"‏اضافی سیکیورٹی کیلئے PIN درکار ہے"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"اضافی سیکیورٹی کیلئے پاس ورڈ درکار ہے"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"جب آپ پروفائل سوئچ کرتے ہیں تو پیٹرن درکار ہوتا ہے"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"‏جب آپ پروفائل سوئچ کرتے ہیں تو PIN درکار ہوتا ہے"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"جب آپ پروفائل سوئچ کرتے ہیں تو پاس ورڈ درکار ہوتا ہے"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"آلہ منتظم کی جانب سے مقفل ہے"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"آلہ کو دستی طور پر مقفل کیا گیا تھا"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">آلہ <xliff:g id="NUMBER_1">%d</xliff:g> گھنٹوں سے غیر مقفل نہیں کیا گیا۔ پیٹرن کی توثیق کریں۔</item>
-      <item quantity="one">آلہ <xliff:g id="NUMBER_0">%d</xliff:g> گھنٹہ سے غیر مقفل نہیں کیا گیا۔ پیٹرن کی توثیق کریں۔</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">‏آلہ <xliff:g id="NUMBER_1">%d</xliff:g> گھنٹوں سے غیر مقفل نہیں کیا گیا۔ PIN کی توثیق کریں۔</item>
-      <item quantity="one">‏آلہ <xliff:g id="NUMBER_0">%d</xliff:g> گھنٹہ سے غیر مقفل نہیں کیا گیا۔ PIN کی توثیق کریں۔</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">آلہ <xliff:g id="NUMBER_1">%d</xliff:g> گھنٹوں سے غیر مقفل نہیں کیا گيا۔ پاس ورڈ کی توثیق کریں۔</item>
-      <item quantity="one">آلہ <xliff:g id="NUMBER_0">%d</xliff:g> گھنٹہ سے غیر مقفل نہیں کیا گیا۔ پاس ورڈ کی توثیق کریں۔</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"تسلیم شدہ نہیں ہے"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"تسلیم شدہ نہیں ہے"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-uz/strings.xml b/packages/SystemUI/res-keyguard/values-uz/strings.xml
index 87452dd..5d281fa 100644
--- a/packages/SystemUI/res-keyguard/values-uz/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-uz/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyguard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"PIN kodni kiriting"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"SIM karta PUK kodi va yangi PIN kodni tering"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM karta PUK kodi"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Yangi SIM karta PIN kodi"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Parolni kiritish uchun bosing"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Qulfni ochish uchun parolni kiriting"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Qulfni ochish uchun PIN kodni kiriting"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"PIN kodni kiriting"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Grafik kalitni chizing"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Parolni kiriting"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN kodi xato."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"SIM karta yaroqsiz."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Quvvat oldi"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Simsiz quvvatlanyapti"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Tezkor quvvat olmoqda"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Sekin quvvat olmoqda"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Quvvatlash vaqtincha cheklangan"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Quvvatlash moslamasini ulang."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Qulfdan chiqarish uchun Menyu tugmasini bosing."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Tarmoq qulflangan"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"SIM karta solinmagan"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Qurilma paroli"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM karta PIN kodi maydoni"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM karta PUK kodi maydoni"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Signal <xliff:g id="ALARM">%1$s</xliff:g> da chalinadi."</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"O‘chirib tashlash"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"eSIMni faolsizlantirish"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"eSIM faolsizlantirilmadi"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Xatolik tufayli eSIM faolsizlantirilmadi."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter tugmasi"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Grafik kalit esimdan chiqdi"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Grafik kalit xato"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Parol xato"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN kod xato"</string>
@@ -68,12 +56,9 @@
       <item quantity="other"><xliff:g id="NUMBER">%d</xliff:g> soniyadan keyin qaytadan urining.</item>
       <item quantity="one">1 soniyadan keyin qaytadan urining.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Grafik kalit chizing"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"SIM karta PIN kodini kiriting."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"“<xliff:g id="CARRIER">%1$s</xliff:g>” SIM kartasi PIN kodini kiriting."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Qurilmadan mobil xizmatlarsiz foydalanish uchun eSIMni faolsizlantiring."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"PIN kodni kiriting"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Parol kiriting"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM karta hozir o‘chirilgan. Davom etish uchun PUK kodni kiriting. Batafsil axborot olish uchun tarmoq operatori bilan bog‘laning."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"“<xliff:g id="CARRIER">%1$s</xliff:g>” SIM kartasi o‘chirib qo‘yildi. Davom etish uchun PUK kodni kiriting. Tafsilotlar uchun aloqa operatoringizga murojaat qiling."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"So‘ralgan PIN kodni kiriting"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"SIM karta qulfi ochilmoqda…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"4-8 ta raqamdan iborat PIN kodni kiriting."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK kod kamida 8 ta raqamdan iborat bo‘lishi shart."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"To‘g‘ri PUK kodni qayta kiriting. Qayta-qayta urinishlar SIM kartani butunlay o‘chirib qo‘yadi."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Grafik kalit juda ko‘p marta chizildi"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"PIN kod <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato kiritildi. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan keyin qaytadan urining."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Parol <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato kiritildi. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan keyin qaytadan urining."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Grafik kalit <xliff:g id="NUMBER_0">%1$d</xliff:g> marta xato kiritildi. \n\n <xliff:g id="NUMBER_1">%2$d</xliff:g> soniyadan keyin qayta urining."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM kartani qulfdan chiqarib bo‘lmadi!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM kartani qulfdan chiqarib bo‘lmadi!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Kod qabul qilindi!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Aloqa yo‘q."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Matn kiritish usulini almashtirish"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Parvoz rejimi"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Qurilma qayta ishga tushganidan keyin grafik kalitni kiritish zarur"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Qo‘shimcha xavfsizlik chorasi sifatida grafik kalit talab qilinadi"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Qo‘shimcha xavfsizlik chorasi sifatida PIN kod talab qilinadi"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Qo‘shimcha xavfsizlik chorasi sifatida parol talab qilinadi"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Profilni amlashtirishda grafik kalit talab qilinadi"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Profilni amlashtirishda PIN kod talab qilinadi"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Profilni amlashtirishda parol talab qilinadi"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Qurilma administrator tomonidan bloklangan"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Qurilma qo‘lda qulflangan"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Qurilma <xliff:g id="NUMBER_1">%d</xliff:g> soatdan beri qulfdan chiqarilgani yo‘q. Chizmali kalitni yana bir marta kiriting.</item>
-      <item quantity="one">Qurilma <xliff:g id="NUMBER_0">%d</xliff:g> soatdan beri qulfdan chiqarilgani yo‘q. Chizmali kalitni yana bir marta kiriting.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Qurilma <xliff:g id="NUMBER_1">%d</xliff:g> soatdan beri qulfdan chiqarilgani yo‘q. PIN kodni yana bir marta kiriting.</item>
-      <item quantity="one">Qurilma <xliff:g id="NUMBER_0">%d</xliff:g> soatdan beri qulfdan chiqarilgani yo‘q. PIN kodni yana bir marta kiriting.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Qurilma <xliff:g id="NUMBER_1">%d</xliff:g> soatdan beri qulfdan chiqarilgani yo‘q. Parolni yana bir marta kiriting.</item>
-      <item quantity="one">Qurilma <xliff:g id="NUMBER_0">%d</xliff:g> soatdan beri qulfdan chiqarilgani yo‘q. Parolni yana bir marta kiriting.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Aniqlanmadi"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Aniqlanmadi"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-vi/strings.xml b/packages/SystemUI/res-keyguard/values-vi/strings.xml
index be10a50..52d64b9 100644
--- a/packages/SystemUI/res-keyguard/values-vi/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-vi/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Khóa bàn phím"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Nhập mã PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Nhập mã PIN mới và mã PUK của SIM"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Mã PUK của SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Mã PIN mới của SIM"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Chạm để nhập mật khẩu"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Nhập mật khẩu để mở khóa"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Nhập mã PIN để mở khóa"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Nhập mã PIN của bạn"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Nhập hình mở khóa của bạn"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Nhập mật khẩu của bạn"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Mã PIN không chính xác."</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Thẻ không hợp lệ."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Đã sạc đầy"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc không dây"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc nhanh"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Đang sạc chậm"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Chức năng sạc tạm thời bị hạn chế"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Kết nối bộ sạc của bạn."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Nhấn vào Menu để mở khóa."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Mạng đã bị khóa"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Không có thẻ SIM"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Mật khẩu thiết bị"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Khu vực mã PIN của SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Khu vực mã PUK của SIM"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"Báo thức tiếp theo được đặt cho <xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Xóa"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Vô hiệu hóa eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Không thể tắt eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"Không thể tắt eSIM do lỗi."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Nhập"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Đã quên hình mở khóa"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Hình mở khóa không chính xác"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Mật khẩu sai"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Mã PIN sai"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">Hãy thử lại sau <xliff:g id="NUMBER">%d</xliff:g> giây.</item>
       <item quantity="one">Hãy thử lại sau 1 giây.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Vẽ hình mở khóa của bạn"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Nhập mã PIN của SIM."</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Nhập mã PIN của SIM dành cho \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Tắt eSIM để sử dụng thiết bị khi không có dịch vụ di động."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Nhập mã PIN"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Nhập mật khẩu"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM hiện bị vô hiệu hóa. Hãy nhập mã PUK để tiếp tục. Liên hệ với nhà cung cấp dịch vụ để biết chi tiết."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\" hiện bị vô hiệu hóa. Hãy nhập mã PUK để tiếp tục. Liên hệ với nhà cung cấp dịch vụ để biết chi tiết."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Nhập mã PIN mong muốn"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Đang mở khóa thẻ SIM…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Nhập mã PIN có từ 4 đến 8 số."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Mã PUK phải có từ 8 số trở lên."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Hãy nhập lại mã PUK chính xác. Nhiều lần lặp lại sẽ vô hiệu hóa vĩnh viễn thẻ SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Quá nhiều lần nhập hình mở khóa"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Bạn đã nhập sai mã PIN <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. \n\nHãy thử lại sau <xliff:g id="NUMBER_1">%2$d</xliff:g> giây."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Bạn đã nhập sai mật khẩu <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. \n\nHãy thử lại sau <xliff:g id="NUMBER_1">%2$d</xliff:g> giây."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Bạn đã vẽ không chính xác hình mở khóa <xliff:g id="NUMBER_0">%1$d</xliff:g> lần. \n\nHãy thử lại sau <xliff:g id="NUMBER_1">%2$d</xliff:g> giây."</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Thao tác mã PIN của SIM không thành công!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Thao tác mã PUK của SIM không thành công!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Mã được chấp nhận!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Không có dịch vụ."</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Chuyển phương thức nhập"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Chế độ trên máy bay"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Yêu cầu hình mở khóa sau khi thiết bị khởi động lại"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Yêu cầu hình mở khóa để bảo mật thêm"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Yêu cầu mã PIN để bảo mật thêm"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Yêu cầu mật khẩu để bảo mật thêm"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Yêu cầu hình mở khóa khi bạn chuyển đổi hồ sơ"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Yêu cầu mã PIN khi bạn chuyển đổi hồ sơ"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Yêu cầu mật khẩu khi bạn chuyển đổi hồ sơ"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Thiết bị đã bị quản trị viên khóa"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Thiết bị đã bị khóa theo cách thủ công"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">Thiết bị đã không được mở khóa trong <xliff:g id="NUMBER_1">%d</xliff:g> giờ. Xác nhận hình mở khóa.</item>
-      <item quantity="one">Thiết bị đã không được mở khóa trong <xliff:g id="NUMBER_0">%d</xliff:g> giờ. Xác nhận hình mở khóa.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">Thiết bị đã không được mở khóa trong <xliff:g id="NUMBER_1">%d</xliff:g> giờ. Xác nhận mã PIN.</item>
-      <item quantity="one">Thiết bị đã không được mở khóa trong <xliff:g id="NUMBER_0">%d</xliff:g> giờ. Xác nhận mã PIN.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">Thiết bị đã không được mở khóa trong <xliff:g id="NUMBER_1">%d</xliff:g> giờ. Xác nhận mật khẩu.</item>
-      <item quantity="one">Thiết bị đã không được mở khóa trong <xliff:g id="NUMBER_0">%d</xliff:g> giờ. Xác nhận mật khẩu.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Không nhận dạng được"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Không nhận dạng được"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
index d57ff9c..4be7908 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rCN/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Keyboard"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"请输入 PIN 码"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"请输入 SIM 卡 PUK 码和新的 PIN 码"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM 卡 PUK 码"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"新 SIM 卡 PIN 码"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"触摸即可输入密码"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"输入密码即可解锁"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"输入 PIN 码即可解锁"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"输入您的 PIN 码"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"绘制您的图案"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"输入您的密码"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN 码有误。"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"SIM 卡无效。"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"已充满电"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在无线充电"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在快速充电"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 正在慢速充电"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充电暂时受限"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"请连接充电器。"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按“菜单”即可解锁。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"网络已锁定"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"没有 SIM 卡"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"设备密码"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM 卡 PIN 码区域"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM 卡 PUK 码区域"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"下一个闹钟时间已设置为<xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"删除"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"停用 eSIM 卡"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"无法停用 eSIM 卡"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"出现错误,无法停用 eSIM 卡。"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"输入"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"忘记了图案"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"图案错误"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"密码错误"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN 码错误"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">请在 <xliff:g id="NUMBER">%d</xliff:g> 秒后重试。</item>
       <item quantity="one">请在 1 秒后重试。</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"绘制您的图案"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"请输入 SIM 卡 PIN 码。"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"请输入“<xliff:g id="CARRIER">%1$s</xliff:g>”的 SIM 卡 PIN 码。"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g>停用 eSIM 卡即可在没有移动服务的情况下使用设备。"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"请输入 PIN 码"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"请输入密码"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM 卡现已停用,需要输入 PUK 码才能继续使用。要了解详情,请联系您的运营商。"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM 卡“<xliff:g id="CARRIER">%1$s</xliff:g>”现已停用,需要输入 PUK 码才能继续使用。要了解详情,请联系您的运营商。"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"请输入所需的 PIN 码"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"正在解锁 SIM 卡…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"请输入 4 到 8 位数的 PIN 码。"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK 码应至少包含 8 位数字。"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"请重新输入正确的 PUK 码。如果屡次输入错误,SIM 卡将被永久停用。"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"图案尝试次数过多"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"您已经 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次输错 PIN 码。\n\n请在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒后重试。"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"您已经 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次输错密码。\n\n请在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒后重试。"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"您已经 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次画错解锁图案。\n\n请在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒后重试。"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM 卡 PIN 码操作失败!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM 卡 PUK 码操作失败!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"代码正确!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"无服务。"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"切换输入法"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"飞行模式"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"重启设备后需要绘制解锁图案"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"需要绘制解锁图案以进一步确保安全"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"需要输入 PIN 码以进一步确保安全"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"需要输入密码以进一步确保安全"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"切换资料后需要绘制解锁图案"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"切换资料后需要输入 PIN 码"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"切换资料后需要输入密码"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"管理员已锁定设备"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"此设备已手动锁定"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">设备已保持锁定状态达 <xliff:g id="NUMBER_1">%d</xliff:g> 小时。请确认解锁图案。</item>
-      <item quantity="one">设备已保持锁定状态达 <xliff:g id="NUMBER_0">%d</xliff:g> 小时。请确认解锁图案。</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">设备已保持锁定状态达 <xliff:g id="NUMBER_1">%d</xliff:g> 小时。请确认 PIN 码。</item>
-      <item quantity="one">设备已保持锁定状态达 <xliff:g id="NUMBER_0">%d</xliff:g> 小时。请确认 PIN 码。</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">设备已保持锁定状态达 <xliff:g id="NUMBER_1">%d</xliff:g> 小时。请确认密码。</item>
-      <item quantity="one">设备已保持锁定状态达 <xliff:g id="NUMBER_0">%d</xliff:g> 小时。请确认密码。</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"无法识别"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"无法识别"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
index 5ecbc9d..7ca7677 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rHK/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"鍵盤鎖"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"輸入 PIN 碼"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"輸入 SIM 卡 PUK 碼和新的 PIN 碼"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM 卡 PUK 碼"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"新的 SIM 卡 PIN 碼"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"輕觸即可輸入密碼"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"輸入密碼即可解鎖"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"輸入 PIN 碼即可解鎖"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"請輸入 PIN"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"請畫出圖案"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"請輸入密碼"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN 碼不正確。"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"SIM 卡無效。"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"已完成充電"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 無線充電中"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 充電暫時受限"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按下 [選單] 即可解鎖。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"網絡已鎖定"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"沒有 SIM 卡"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"裝置密碼"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM 卡 PIN 區域"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM 卡 PUK 區域"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"已經將下一個鬧鐘時間設做<xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Delete 鍵 (刪除)"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"停用 eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"無法停用 eSIM 卡"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"發生錯誤,因此無法停用此 eSIM 卡。"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter 鍵 (輸入)"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"忘記上鎖圖案"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"圖案錯誤"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"密碼錯誤"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN 碼錯誤"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">請在 <xliff:g id="NUMBER">%d</xliff:g> 秒後再試一次。</item>
       <item quantity="one">請在 1 秒後再試一次。</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"畫出上鎖圖案"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"輸入 SIM 卡的 PIN 碼。"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"輸入「<xliff:g id="CARRIER">%1$s</xliff:g>」SIM 卡的 PIN 碼。"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> 停用 eSIM 卡,即可在沒有流動服務的情況下使用裝置。"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"輸入 PIN 碼"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"輸入密碼"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM 卡現已停用,請輸入 PUK 碼以繼續。詳情請與流動網絡供應商聯絡。"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM 卡「<xliff:g id="CARRIER">%1$s</xliff:g>」現已停用,請輸入 PUK 碼以繼續。詳情請與流動網絡供應商聯絡。"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"輸入所需的 PIN 碼"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"正在解鎖 SIM 卡…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"請輸入 4 至 8 位數的 PIN 碼。"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK 碼應由 8 個或以上數字組成。"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"請重新輸入正確的 PUK 碼。如果錯誤輸入的次數過多,SIM 卡將永久停用。"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"上鎖圖案畫錯次數過多"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"您已輸入錯誤的 PIN 碼 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"您已輸入錯誤的密碼 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"您已畫錯解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"無法使用 SIM 卡 PIN 碼解鎖!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"無法使用 SIM 卡 PUK 碼解鎖!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"PIN 碼正確!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"沒有服務。"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"轉換輸入方法"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"飛行模式"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"裝置重新啟動後,必須畫出上鎖圖案才能使用"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"請務必畫出上鎖圖案,以進一步確保安全"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"請務必輸入 PIN 碼,以進一步確保安全"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"請務必輸入密碼,以進一步確保安全"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"切換設定檔時必須畫出上鎖圖案"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"切換設定檔時必須輸入 PIN 碼"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"切換設定檔時必須輸入密碼"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"裝置已由管理員鎖定"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"使用者已手動將裝置上鎖"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">裝置在過去 <xliff:g id="NUMBER_1">%d</xliff:g> 小時內未有解鎖,請確認上鎖圖案。</item>
-      <item quantity="one">裝置在過去 <xliff:g id="NUMBER_0">%d</xliff:g> 小時內未有解鎖,請確認上鎖圖案。</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">裝置在過去 <xliff:g id="NUMBER_1">%d</xliff:g> 小時內未有解鎖,請確認 PIN 碼。</item>
-      <item quantity="one">裝置在過去 <xliff:g id="NUMBER_0">%d</xliff:g> 小時內未有解鎖,請確認 PIN 碼。</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">裝置在過去 <xliff:g id="NUMBER_1">%d</xliff:g> 小時內未有解鎖,請確認密碼。</item>
-      <item quantity="one">裝置在過去 <xliff:g id="NUMBER_0">%d</xliff:g> 小時內未有解鎖,請確認密碼。</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"未能識別"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"未能識別"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
index 621fe49..d3802c5 100644
--- a/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zh-rTW/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"鍵盤鎖"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"輸入 PIN 碼"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"輸入 SIM 卡 PUK 碼和新 PIN 碼"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"SIM 卡 PUK 碼"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"新增 SIM 卡 PIN 碼"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"輕觸即可輸入密碼"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"輸入密碼即可解鎖"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"輸入 PIN 碼即可解鎖"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"輸入 PIN 碼"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"畫出解鎖圖案"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"輸入密碼"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"PIN 碼不正確。"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"卡片無效。"</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"充電完成"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 無線充電"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 快速充電中"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 慢速充電中"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • 已暫時限制充電"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"請連接充電器。"</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"按選單鍵解鎖。"</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"網路已鎖定"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"沒有 SIM 卡"</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"裝置密碼"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"SIM 卡 PIN 區"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"SIM 卡 PUK 區"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"已設定下一個鬧鐘時間:<xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"刪除"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"停用 eSIM 卡"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"無法停用 eSIM 卡"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"發生錯誤,因此無法停用 eSIM 卡。"</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Enter 鍵"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"忘記解鎖圖案"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"圖案錯誤"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"密碼錯誤"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN 碼錯誤"</string>
@@ -68,12 +56,9 @@
       <item quantity="other">請於 <xliff:g id="NUMBER">%d</xliff:g> 秒後再試一次。</item>
       <item quantity="one">請於 1 秒後再試一次。</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"畫出解鎖圖案"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"輸入 SIM 卡的 PIN 碼。"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"輸入「<xliff:g id="CARRIER">%1$s</xliff:g>」SIM 卡的 PIN 碼。"</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g>停用 eSIM 卡即可在沒有行動服務的情況下使用裝置。"</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"輸入 PIN 碼"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"輸入密碼"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"SIM 卡已遭停用,輸入 PUK 碼即可繼續使用。如需瞭解詳情,請與電信業者聯絡。"</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"SIM 卡「<xliff:g id="CARRIER">%1$s</xliff:g>」現已遭停用,輸入 PUK 碼即可繼續使用。如需瞭解詳情,請與電信業者聯絡。"</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"輸入所需的 PIN 碼"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"正在解除 SIM 卡鎖定…"</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"請輸入 4 到 8 碼的 PIN 碼。"</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"PUK 碼至少必須為 8 碼。"</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"請重新輸入正確的 PUK 碼。如果錯誤次數過多,SIM 卡將會遭到永久停用。"</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"解鎖圖案畫錯次數過多"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"你已輸入錯誤的 PIN 碼 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"你已輸入錯誤的密碼 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"你已畫出錯誤的解鎖圖案 <xliff:g id="NUMBER_0">%1$d</xliff:g> 次。\n\n請在 <xliff:g id="NUMBER_1">%2$d</xliff:g> 秒後再試一次。"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"SIM 卡 PIN 碼解鎖失敗!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"SIM 卡 PUK 碼解鎖失敗!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"PIN 碼正確!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"沒有服務。"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"切換輸入法"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"飛航模式"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"裝置重新啟動後需要畫出解鎖圖案"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"請畫出解鎖圖案,以進一步確保資訊安全"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"請輸入 PIN 碼,以進一步確保資訊安全"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"請輸入密碼,以進一步確保資訊安全"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"切換設定檔時需要畫出解鎖圖案"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"切換設定檔時需要輸入 PIN 碼"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"切換設定檔時需要輸入密碼"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"管理員已鎖定裝置"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"裝置已手動鎖定"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="other">裝置已有 <xliff:g id="NUMBER_1">%d</xliff:g> 小時未解鎖。請確認解鎖圖案。</item>
-      <item quantity="one">裝置已有 <xliff:g id="NUMBER_0">%d</xliff:g> 小時未解鎖。請確認解鎖圖案。</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="other">裝置已有 <xliff:g id="NUMBER_1">%d</xliff:g> 小時未解鎖。請確認 PIN 碼。</item>
-      <item quantity="one">裝置已有 <xliff:g id="NUMBER_0">%d</xliff:g> 小時未解鎖。請確認 PIN 碼。</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="other">裝置已有 <xliff:g id="NUMBER_1">%d</xliff:g> 小時未解鎖。請確認密碼。</item>
-      <item quantity="one">裝置已有 <xliff:g id="NUMBER_0">%d</xliff:g> 小時未解鎖。請確認密碼。</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"無法識別"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"無法識別"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values-zu/strings.xml b/packages/SystemUI/res-keyguard/values-zu/strings.xml
index aefd744..5440b00 100644
--- a/packages/SystemUI/res-keyguard/values-zu/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-zu/strings.xml
@@ -20,18 +20,9 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="514691256816366517">"Ukhiye wokugada"</string>
-    <string name="keyguard_password_enter_pin_code" msgid="8582296866585566671">"Faka ikhodi ye-PIN"</string>
-    <string name="keyguard_password_enter_puk_code" msgid="3813154965969758868">"Thayipha i-PUK ye-SIM nekhodi yephinikhodi entsha"</string>
-    <string name="keyguard_password_enter_puk_prompt" msgid="3529260761374385243">"Ikhodi ye-PUK ye-SIM"</string>
-    <string name="keyguard_password_enter_pin_prompt" msgid="2304037870481240781">"Ikhodi Entsha ye-SIM PIN"</string>
-    <string name="keyguard_password_entry_touch_hint" msgid="6180028658339706333"><font size="17">"Thinta ukuze uthayiphe iphasiwedi"</font></string>
-    <string name="keyguard_password_enter_password_code" msgid="7393393239623946777">"Bhala iphasiwedi ukuze kuvuleke"</string>
-    <string name="keyguard_password_enter_pin_password_code" msgid="3692259677395250509">"Faka i-PIN ukuvula"</string>
     <string name="keyguard_enter_your_pin" msgid="5429932527814874032">"Faka iPHINIKHODI yakho"</string>
     <string name="keyguard_enter_your_pattern" msgid="351503370332324745">"Faka iphethini yakho"</string>
     <string name="keyguard_enter_your_password" msgid="7225626204122735501">"Faka iphasiwedi yakho"</string>
-    <string name="keyguard_password_wrong_pin_code" msgid="3514267777289393046">"Ikhodi ye-PIN engalungile!"</string>
     <string name="keyguard_sim_error_message_short" msgid="633630844240494070">"Ikhadi elingavumelekile."</string>
     <string name="keyguard_charged" msgid="5478247181205188995">"Kushajiwe"</string>
     <string name="keyguard_plugged_in_wireless" msgid="2537874724955057383">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Iyashaja ngaphandle kwentambo"</string>
@@ -39,7 +30,6 @@
     <string name="keyguard_plugged_in_charging_fast" msgid="4386594091107340426">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kaningi"</string>
     <string name="keyguard_plugged_in_charging_slowly" msgid="217655355424210">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ishaja kancane"</string>
     <string name="keyguard_plugged_in_charging_limited" msgid="6091488837901216962">"<xliff:g id="PERCENTAGE">%s</xliff:g> • Ukushaja kukhawulelwe okwesikhashana"</string>
-    <string name="keyguard_low_battery" msgid="1868012396800230904">"Xhuma ishaja yakho."</string>
     <string name="keyguard_instructions_when_pattern_disabled" msgid="8448804180089936954">"Chofoza Menyu ukuvula."</string>
     <string name="keyguard_network_locked_message" msgid="407096292844868608">"Inethiwekhi ivaliwe"</string>
     <string name="keyguard_missing_sim_message_short" msgid="704159478161444907">"Alikho ikhadi le-SIM."</string>
@@ -54,13 +44,11 @@
     <string name="keyguard_accessibility_password" msgid="3524161948484801450">"Iphasiwedi yedivayisi"</string>
     <string name="keyguard_accessibility_sim_pin_area" msgid="6272116591533888062">"Indawo yephinikhodi ye-SIM"</string>
     <string name="keyguard_accessibility_sim_puk_area" msgid="5537294043180237374">"Indawo ye-SIM PUK"</string>
-    <string name="keyguard_accessibility_next_alarm" msgid="4492876946798984630">"I-alamu elandelayo esethelwe i-<xliff:g id="ALARM">%1$s</xliff:g>"</string>
     <string name="keyboardview_keycode_delete" msgid="8489719929424895174">"Susa"</string>
     <string name="disable_carrier_button_text" msgid="7153361131709275746">"Khubaza i-eSIM"</string>
     <string name="error_disable_esim_title" msgid="3802652622784813119">"Ayikwazi ukukhubaz i-eSIM"</string>
     <string name="error_disable_esim_msg" msgid="2441188596467999327">"I-eSIM ayikwakhi ukukhutshazwa ngenxa yephutha."</string>
     <string name="keyboardview_keycode_enter" msgid="6727192265631761174">"Faka"</string>
-    <string name="kg_forgot_pattern_button_text" msgid="3304688032024541260">"Ukhohlwe iphethini?"</string>
     <string name="kg_wrong_pattern" msgid="5907301342430102842">"Iphethini engalungile"</string>
     <string name="kg_wrong_password" msgid="4143127991071670512">"Iphasiwedi engalungile"</string>
     <string name="kg_wrong_pin" msgid="4160978845968732624">"Iphinikhodi engalungile"</string>
@@ -68,12 +56,9 @@
       <item quantity="one">Zama futhi kumasekhondi angu-<xliff:g id="NUMBER">%d</xliff:g>.</item>
       <item quantity="other">Zama futhi kumasekhondi angu-<xliff:g id="NUMBER">%d</xliff:g>.</item>
     </plurals>
-    <string name="kg_pattern_instructions" msgid="5376036737065051736">"Dweba iphethini yakho"</string>
     <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Faka i-PIN ye-SIM"</string>
     <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Faka i-PIN ye-SIM ye-\"<xliff:g id="CARRIER">%1$s</xliff:g>\""</string>
     <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Khubaza i-eSIM ukuze usebenzise le sevisi yeselula."</string>
-    <string name="kg_pin_instructions" msgid="822353548385014361">"Faka iphinikhodi"</string>
-    <string name="kg_password_instructions" msgid="324455062831719903">"Faka iphasiwedi"</string>
     <string name="kg_puk_enter_puk_hint" msgid="3005288372875367017">"I-SIM manje ikhutshaziwe. Faka ikhodi ye-PUK ukuze uqhubeke. Xhumana nenkampani yenethiwekhi ngemininingwane."</string>
     <string name="kg_puk_enter_puk_hint_multi" msgid="4876780689904862943">"I-SIM ye-\"<xliff:g id="CARRIER">%1$s</xliff:g>\" manje ikhutshaziwe. Faka ikhodi ye-PUK ukuze uqhubeke. Xhumana nenkampani yenethiwekhi ukuze uthole imininingwane."</string>
     <string name="kg_puk_enter_pin_hint" msgid="6028432138916150399">"Faka iphinikhodi oyithandayo"</string>
@@ -81,8 +66,6 @@
     <string name="kg_sim_unlock_progress_dialog_message" msgid="4251352015304070326">"Ivula ikhadi le-SIM..."</string>
     <string name="kg_invalid_sim_pin_hint" msgid="2762202646949552978">"Thayipha i-PIN enezinombolo ezingu-4 kuya kwezingu-8."</string>
     <string name="kg_invalid_sim_puk_hint" msgid="5319756880543857694">"Ikhodi ye-PUK kufanele ibe yizinombolo ezingu-8 noma eziningi."</string>
-    <string name="kg_invalid_puk" msgid="1774337070084931186">"Faka kabusha ikhodi ye-PUK elungile. Imizamo ephindiwe izokhubaza unaphakade i-SIM."</string>
-    <string name="kg_login_too_many_attempts" msgid="4519957179182578690">"Kunemizamo eminingi kakhulu yephathini!"</string>
     <string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="544687656831558971">"Ubhale iphinikhodi ykho ngendlela engafanele izikhathi ezingu-<xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\nZama futhi emasekhondini angu-<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Ubhale iphasiwedi yakho ngendlela engafanele <xliff:g id="NUMBER_0">%1$d</xliff:g> izikhathi. \n\nZama futhi emasekhondini angu-<xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
     <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Udwebe iphathini yakho yokuvula ngendlela engafanele-<xliff:g id="NUMBER_0">%1$d</xliff:g>. \n\n Zama futhi emasekhondini angu-<xliff:g id="NUMBER_1">%2$d</xliff:g>"</string>
@@ -98,8 +81,6 @@
     </plurals>
     <string name="kg_password_pin_failed" msgid="5136259126330604009">"Umsebenzi wephinikhodi ye-SIM wehlulekile!"</string>
     <string name="kg_password_puk_failed" msgid="6778867411556937118">"Umsebenzi we-PUK ye-SIM wehlulekile!"</string>
-    <string name="kg_pin_accepted" msgid="1625501841604389716">"Ikhodi yamukelwe!"</string>
-    <string name="keyguard_carrier_default" msgid="6359808469637388586">"Ayikho isevisi"</string>
     <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Shintsha indlela yokufaka"</string>
     <string name="airplane_mode" msgid="2528005343938497866">"Imodi yendiza"</string>
     <string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"Iphethini iyadingeka ngemuva kokuqala kabusha kwedivayisi"</string>
@@ -108,23 +89,8 @@
     <string name="kg_prompt_reason_timeout_pattern" msgid="9170360502528959889">"Kudingeka iphethini  ngokuvikeleka okungeziwe"</string>
     <string name="kg_prompt_reason_timeout_pin" msgid="5945186097160029201">"Kudingeka iphinikhodi ngokuvikeleka okungeziwe"</string>
     <string name="kg_prompt_reason_timeout_password" msgid="2258263949430384278">"Iphasiwedi idingelwa ukuvikela okungeziwe"</string>
-    <string name="kg_prompt_reason_switch_profiles_pattern" msgid="1922016914701991230">"Iphethini iyadingeka uma ushintsha amaphrofayela"</string>
-    <string name="kg_prompt_reason_switch_profiles_pin" msgid="6490434826361055400">"Kudingeka iphinikhodi uma ushintsha amaphrofayela"</string>
-    <string name="kg_prompt_reason_switch_profiles_password" msgid="1680374696393804441">"Iphasiwedi iyadingeka uma ushintsha amaphrofayela"</string>
     <string name="kg_prompt_reason_device_admin" msgid="6961159596224055685">"Idivayisi ikhiywe ngumlawuli"</string>
     <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Idivayisi ikhiywe ngokwenza"</string>
-    <plurals name="kg_prompt_reason_time_pattern" formatted="false" msgid="1337428979661197957">
-      <item quantity="one">Idivayisi ayikavulwa ngamahora angu-<xliff:g id="NUMBER_1">%d</xliff:g>. Qinisekisa iphethini.</item>
-      <item quantity="other">Idivayisi ayikavulwa ngamahora angu-<xliff:g id="NUMBER_1">%d</xliff:g>. Qinisekisa iphethini.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_pin" formatted="false" msgid="6444519502336330270">
-      <item quantity="one">Idivayisi ayikavulwa ngamahora angu-<xliff:g id="NUMBER_1">%d</xliff:g>. Qinisekisa iphinikhodi.</item>
-      <item quantity="other">Idivayisi ayikavulwa ngamahora angu-<xliff:g id="NUMBER_1">%d</xliff:g>. Qinisekisa iphinikhodi.</item>
-    </plurals>
-    <plurals name="kg_prompt_reason_time_password" formatted="false" msgid="5343961527665116914">
-      <item quantity="one">Idivayisi ayikavulwa ngamahora angu-<xliff:g id="NUMBER_1">%d</xliff:g>. Qinisekisa iphasiwedi.</item>
-      <item quantity="other">Idivayisi ayikavulwa ngamahora angu-<xliff:g id="NUMBER_1">%d</xliff:g>. Qinisekisa iphasiwedi.</item>
-    </plurals>
     <string name="kg_fingerprint_not_recognized" msgid="5982606907039479545">"Akwaziwa"</string>
     <string name="kg_face_not_recognized" msgid="7903950626744419160">"Akwaziwa"</string>
     <plurals name="kg_password_default_pin_message" formatted="false" msgid="7730152526369857818">
diff --git a/packages/SystemUI/res-keyguard/values/config.xml b/packages/SystemUI/res-keyguard/values/config.xml
index 6176f7c..6194aa0 100644
--- a/packages/SystemUI/res-keyguard/values/config.xml
+++ b/packages/SystemUI/res-keyguard/values/config.xml
@@ -22,5 +22,11 @@
 
     <!-- Allow the menu hard key to be disabled in LockScreen on some devices [DO NOT TRANSLATE] -->
     <bool name="config_disableMenuKeyInLockScreen">false</bool>
+    <!-- Allows PIN/Pattern to be drawn on one side of a display, and for the user to
+         switch sides -->
     <bool name="can_use_one_handed_bouncer">false</bool>
+    <!-- Will display the bouncer on one side of the display, and the current user icon and
+         user switcher on the other side -->
+    <bool name="bouncer_display_user_switcher">false</bool>
+
 </resources>
diff --git a/packages/SystemUI/res-product/values-as/strings.xml b/packages/SystemUI/res-product/values-as/strings.xml
index c3e965c..aa9cb2d 100644
--- a/packages/SystemUI/res-product/values-as/strings.xml
+++ b/packages/SystemUI/res-product/values-as/strings.xml
@@ -26,18 +26,18 @@
     <string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"টেবলেটটোত ছিম কার্ড নাই।"</string>
     <string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"ফ’নটোত ছিম কার্ড নাই।"</string>
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"পিন ক’ড মিলা নাই"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই টেবলেটটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ সকলো ডেটা মচি পেলাব।"</string>
-    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই ফ’নটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ সকলো ডেটা মচি পেলাব।"</string>
-    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই টেবলেটটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ সকলো ডেটা মচি পেলাব।"</string>
-    <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই ফ’নটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ সকলো ডেটা মচি পেলাব।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে ব্যৱহাৰকাৰীৰ সকলো ডেটা মচি পেলাব।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে ব্যৱহাৰকাৰীৰ সকলো ডেটা মচি পেলাব।"</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে ব্যৱহাৰকাৰীৰ সকলো ডেটা মচি পেলাব।"</string>
-    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে  ব্যৱহাৰকাৰীৰ সকলো ডেটা মচি পেলাব।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলটোৰ সকলো ডেটা মচি পেলাব।"</string>
-    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলৰ সকলো ডেটা মচি পেলাব।"</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলটোৰ সকলো ডেটা মচি পেলাব।"</string>
-    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলটোৰ সকলো ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই টেবলেটটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই ফ’নটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই টেবলেটটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই ফ’নটো ৰিছেট কৰা হ’ব, যিয়ে ইয়াৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে ব্যৱহাৰকাৰীৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে ব্যৱহাৰকাৰীৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে আটাইবোৰ ব্যৱহাৰকাৰী ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_now_erasing_user" product="default" msgid="3051962486994265014">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। এই ব্যৱহাৰকাৰীজনক আঁতৰোৱা হ’ব, যিয়ে আটাইবোৰ ব্যৱহাৰকাৰী ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="tablet" msgid="1049523640263353830">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলটোৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"আপুনি টেবলেটটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলটোৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
+    <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"আপুনি ফ’নটো আনলক কৰিবলৈ <xliff:g id="NUMBER">%d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰিছে। কৰ্মস্থানৰ প্ৰ’ফাইলটো আঁতৰোৱা হ’ব, যিয়ে প্ৰ’ফাইলটোৰ আটাইবোৰ ডেটা মচি পেলাব।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"আপুনি নিজৰ আনলক কৰা আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাক নিজৰ টেবলেটটো এটা ইমেইল একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ’ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পাছত পুনৰ চেষ্টা কৰক।"</string>
     <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"আপুনি নিজৰ আনলক কৰা আৰ্হিটো <xliff:g id="NUMBER_0">%1$d</xliff:g> বাৰ ভুলকৈ আঁকিছে। আৰু <xliff:g id="NUMBER_1">%2$d</xliff:g> বাৰ ভুলকৈ প্ৰয়াস কৰাৰ পাছত আপোনাক নিজৰ ফ’নটো এটা ইমেইল একাউণ্টৰ জৰিয়তে আনলক কৰিবলৈ কোৱা হ’ব।\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> ছেকেণ্ডৰ পাছত পুনৰ চেষ্টা কৰক।"</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"অধিক বিকল্পৰ বাবে আপোনাৰ ফ’নটো আনলক কৰক"</string>
diff --git a/packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml b/packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml
deleted file mode 100644
index 52ed76d..0000000
--- a/packages/SystemUI/res/drawable/assist_orb_navbar_scrim.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  ~ Copyright (C) 2014 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">
-    <gradient
-            android:type="linear"
-            android:angle="90"
-            android:startColor="#33000000"
-            android:endColor="#00000000" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/assist_orb_scrim.xml b/packages/SystemUI/res/drawable/assist_orb_scrim.xml
deleted file mode 100644
index bbb2617..0000000
--- a/packages/SystemUI/res/drawable/assist_orb_scrim.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  ~ Copyright (C) 2014 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">
-    <gradient
-            android:type="linear"
-            android:angle="90"
-            android:startColor="#55000000"
-            android:endColor="#00000000" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_list.xml b/packages/SystemUI/res/drawable/ic_list.xml
new file mode 100644
index 0000000..7ef5299
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_list.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2021 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.
+-->
+
+<!-- Remove when Fgs manager tile is removed -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="48dp"
+    android:height="48dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:pathData="M2,4h4v4h-4z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M8,4h14v4h-14z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M2,10h4v4h-4z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M8,10h14v4h-14z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M2,16h4v4h-4z"
+        android:fillColor="#000000"/>
+    <path
+        android:pathData="M8,16h14v4h-14z"
+        android:fillColor="#000000"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/media_output_dialog_seekbar_background.xml b/packages/SystemUI/res/drawable/media_output_dialog_seekbar_background.xml
new file mode 100644
index 0000000..3a228d5
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_dialog_seekbar_background.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@android:id/background">
+        <shape>
+            <corners android:radius="28dp" />
+            <solid android:color="@android:color/transparent" />
+            <size
+                android:height="64dp"/>
+        </shape>
+    </item>
+    <item android:id="@android:id/progress">
+        <clip>
+            <shape>
+                <corners
+                    android:radius="28dp"/>
+                <size
+                    android:height="64dp"/>
+                <solid android:color="@*android:color/system_accent1_200" />
+            </shape>
+        </clip>
+    </item>
+</layer-list>
diff --git a/packages/SystemUI/res/drawable/media_output_dialog_solid_button_background.xml b/packages/SystemUI/res/drawable/media_output_dialog_solid_button_background.xml
new file mode 100644
index 0000000..86f8b42
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_dialog_solid_button_background.xml
@@ -0,0 +1,29 @@
+<!--
+  ~ Copyright (C) 2021 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"
+       xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+       android:shape="rectangle">
+    <stroke
+        android:color="@android:color/transparent"
+        android:width="1dp"/>
+    <corners android:radius="20dp"/>
+    <padding
+        android:left="@dimen/media_output_dialog_button_padding_horizontal"
+        android:right="@dimen/media_output_dialog_button_padding_horizontal"
+        android:top="@dimen/media_output_dialog_button_padding_vertical"
+        android:bottom="@dimen/media_output_dialog_button_padding_vertical" />
+    <solid android:color="?androidprv:attr/colorAccentPrimaryVariant" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/prv_text_color_on_accent.xml b/packages/SystemUI/res/drawable/media_output_item_background.xml
similarity index 67%
copy from packages/SystemUI/res/color/prv_text_color_on_accent.xml
copy to packages/SystemUI/res/drawable/media_output_item_background.xml
index 9f44aca..8c23659 100644
--- a/packages/SystemUI/res/color/prv_text_color_on_accent.xml
+++ b/packages/SystemUI/res/drawable/media_output_item_background.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
   ~ Copyright (C) 2021 The Android Open Source Project
   ~
@@ -14,7 +13,11 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<selector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-          xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="?androidprv:attr/textColorOnAccent" />
-</selector>
\ No newline at end of file
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+       android:shape="rectangle">
+    <corners
+        android:radius="16dp"/>
+    <solid android:color="?androidprv:attr/colorAccentSecondary" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/prv_text_color_on_accent.xml b/packages/SystemUI/res/drawable/media_output_item_background_active.xml
similarity index 67%
copy from packages/SystemUI/res/color/prv_text_color_on_accent.xml
copy to packages/SystemUI/res/drawable/media_output_item_background_active.xml
index 9f44aca..09dee95 100644
--- a/packages/SystemUI/res/color/prv_text_color_on_accent.xml
+++ b/packages/SystemUI/res/drawable/media_output_item_background_active.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
   ~ Copyright (C) 2021 The Android Open Source Project
   ~
@@ -14,7 +13,11 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-<selector xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-          xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="?androidprv:attr/textColorOnAccent" />
-</selector>
\ No newline at end of file
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+       xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+       android:shape="rectangle">
+    <corners
+        android:radius="50dp"/>
+    <solid android:color="?androidprv:attr/colorAccentSecondary" />
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/media_output_status_check.xml b/packages/SystemUI/res/drawable/media_output_status_check.xml
new file mode 100644
index 0000000..4e17e48
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_status_check.xml
@@ -0,0 +1,27 @@
+<!--
+  ~ Copyright (C) 2021 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"
+        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="?androidprv:attr/colorAccentPrimaryVariant"
+        android:pathData="M9,16.2L4.8,12l-1.4,1.4L9,19 21,7l-1.4,-1.4L9,16.2z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/media_output_status_failed.xml b/packages/SystemUI/res/drawable/media_output_status_failed.xml
new file mode 100644
index 0000000..81fb92c
--- /dev/null
+++ b/packages/SystemUI/res/drawable/media_output_status_failed.xml
@@ -0,0 +1,27 @@
+<!--
+  ~ Copyright (C) 2021 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"
+        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?attr/colorControlNormal">
+    <path
+        android:fillColor="?androidprv:attr/colorAccentPrimaryVariant"
+        android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/qs_dialog_btn_filled.xml b/packages/SystemUI/res/drawable/qs_dialog_btn_filled.xml
index 1a128df..14cb1de9 100644
--- a/packages/SystemUI/res/drawable/qs_dialog_btn_filled.xml
+++ b/packages/SystemUI/res/drawable/qs_dialog_btn_filled.xml
@@ -16,8 +16,8 @@
   -->
 <inset xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-       android:insetTop="@dimen/qs_dialog_button_vertical_inset"
-       android:insetBottom="@dimen/qs_dialog_button_vertical_inset">
+       android:insetTop="@dimen/dialog_button_vertical_inset"
+       android:insetBottom="@dimen/dialog_button_vertical_inset">
     <ripple android:color="?android:attr/colorControlHighlight">
         <item android:id="@android:id/mask">
             <shape android:shape="rectangle">
@@ -29,10 +29,10 @@
             <shape android:shape="rectangle">
                 <corners android:radius="?android:attr/buttonCornerRadius"/>
                 <solid android:color="?androidprv:attr/colorAccentPrimary"/>
-                <padding android:left="@dimen/qs_dialog_button_horizontal_padding"
-                         android:top="@dimen/qs_dialog_button_vertical_padding"
-                         android:right="@dimen/qs_dialog_button_horizontal_padding"
-                         android:bottom="@dimen/qs_dialog_button_vertical_padding"/>
+                <padding android:left="@dimen/dialog_button_horizontal_padding"
+                         android:top="@dimen/dialog_button_vertical_padding"
+                         android:right="@dimen/dialog_button_horizontal_padding"
+                         android:bottom="@dimen/dialog_button_vertical_padding"/>
             </shape>
         </item>
     </ripple>
diff --git a/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml b/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml
index 467c20f..665b456 100644
--- a/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml
+++ b/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml
@@ -16,8 +16,8 @@
   -->
 <inset xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-       android:insetTop="@dimen/qs_dialog_button_vertical_inset"
-       android:insetBottom="@dimen/qs_dialog_button_vertical_inset">
+       android:insetTop="@dimen/dialog_button_vertical_inset"
+       android:insetBottom="@dimen/dialog_button_vertical_inset">
     <ripple android:color="?android:attr/colorControlHighlight">
         <item android:id="@android:id/mask">
             <shape android:shape="rectangle">
@@ -32,10 +32,10 @@
                 <stroke android:color="?androidprv:attr/colorAccentPrimary"
                         android:width="1dp"
                 />
-                <padding android:left="@dimen/qs_dialog_button_horizontal_padding"
-                         android:top="@dimen/qs_dialog_button_vertical_padding"
-                         android:right="@dimen/qs_dialog_button_horizontal_padding"
-                         android:bottom="@dimen/qs_dialog_button_vertical_padding"/>
+                <padding android:left="@dimen/dialog_button_horizontal_padding"
+                         android:top="@dimen/dialog_button_vertical_padding"
+                         android:right="@dimen/dialog_button_horizontal_padding"
+                         android:bottom="@dimen/dialog_button_vertical_padding"/>
             </shape>
         </item>
     </ripple>
diff --git a/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml b/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml
index 0dec981..991dc63e 100644
--- a/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml
+++ b/packages/SystemUI/res/layout-land-television/volume_dialog_row.xml
@@ -35,7 +35,7 @@
             android:id="@+id/volume_number"
             android:layout_width="@dimen/tv_volume_dialog_bubble_size"
             android:layout_height="@dimen/tv_volume_dialog_bubble_size"
-            android:maxLength="2"
+            android:maxLength="3"
             android:gravity="center"
             android:fontFeatureSettings="tnum"
             android:background="@drawable/tv_volume_dialog_circle"
diff --git a/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml b/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml
new file mode 100644
index 0000000..a3e289a
--- /dev/null
+++ b/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@*android:id/buttonPanel"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:scrollbarAlwaysDrawVerticalTrack="true"
+    android:scrollIndicators="top|bottom"
+    android:fillViewport="true"
+    android:paddingTop="@dimen/dialog_button_bar_top_padding"
+    android:paddingStart="@dimen/dialog_side_padding"
+    android:paddingEnd="@dimen/dialog_side_padding"
+    android:paddingBottom="@dimen/dialog_bottom_padding"
+    style="?android:attr/buttonBarStyle">
+    <com.android.internal.widget.ButtonBarLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layoutDirection="locale"
+        android:orientation="horizontal"
+        android:gravity="bottom">
+
+        <Button
+            android:id="@android:id/button3"
+            style="?android:attr/buttonBarNeutralButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <Space
+            android:id="@*android:id/spacer"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            android:visibility="invisible" />
+
+        <Button
+            android:id="@android:id/button2"
+            style="?android:attr/buttonBarNegativeButtonStyle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+
+        <Button
+            android:id="@android:id/button1"
+            style="?android:attr/buttonBarPositiveButtonStyle"
+            android:layout_marginStart="8dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
+    </com.android.internal.widget.ButtonBarLayout>
+</ScrollView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/alert_dialog_systemui.xml b/packages/SystemUI/res/layout/alert_dialog_systemui.xml
new file mode 100644
index 0000000..f280cbd
--- /dev/null
+++ b/packages/SystemUI/res/layout/alert_dialog_systemui.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2021 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.internal.widget.AlertDialogLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@*android:id/parentPanel"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_horizontal|top"
+    android:orientation="vertical"
+    android:paddingTop="@dimen/dialog_top_padding"
+    >
+
+    <include layout="@layout/alert_dialog_title_systemui" />
+
+    <FrameLayout
+        android:id="@*android:id/contentPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="48dp"
+        android:paddingStart="@dimen/dialog_side_padding"
+        android:paddingEnd="@dimen/dialog_side_padding"
+        >
+
+        <ScrollView
+            android:id="@*android:id/scrollView"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:clipToPadding="false">
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical">
+
+                <Space
+                    android:id="@*android:id/textSpacerNoTitle"
+                    android:visibility="gone"
+                    android:layout_width="match_parent"
+                    android:layout_height="0dp" />
+
+                <TextView
+                    android:id="@*android:id/message"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    style="@style/TextAppearance.Dialog.Body.Message" />
+
+                <Space
+                    android:id="@*android:id/textSpacerNoButtons"
+                    android:visibility="gone"
+                    android:layout_width="match_parent"
+                    android:layout_height="6dp" />
+            </LinearLayout>
+        </ScrollView>
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@*android:id/customPanel"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:minHeight="48dp"
+        android:paddingStart="@dimen/dialog_side_padding"
+        android:paddingEnd="@dimen/dialog_side_padding"
+        >
+
+        <FrameLayout
+            android:id="@*android:id/custom"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+    </FrameLayout>
+
+    <include
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        layout="@layout/alert_dialog_button_bar_systemui" />
+
+</com.android.internal.widget.AlertDialogLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml b/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml
new file mode 100644
index 0000000..480ba00
--- /dev/null
+++ b/packages/SystemUI/res/layout/alert_dialog_title_systemui.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ Copyright (C) 2021 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"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:id="@*android:id/topPanel"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:paddingStart="@dimen/dialog_side_padding"
+    android:paddingEnd="@dimen/dialog_side_padding"
+>
+
+    <!-- If the client uses a customTitle, it will be added here. -->
+
+    <LinearLayout
+        android:id="@*android:id/title_template"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:gravity="center_horizontal|top">
+
+        <ImageView
+            android:id="@*android:id/icon"
+            android:layout_width="32dp"
+            android:layout_height="32dp"
+            android:layout_marginBottom="16dp"
+            android:scaleType="fitCenter"
+            android:src="@null"
+            android:tint="?androidprv:attr/colorAccentPrimaryVariant"
+            />
+
+        <com.android.internal.widget.DialogTitle
+            android:id="@*android:id/alertTitle"
+            android:singleLine="true"
+            android:ellipsize="end"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="16dp"
+            style="@style/TextAppearance.Dialog.Title" />
+    </LinearLayout>
+
+    <Space
+        android:id="@*android:id/titleDividerNoCustom"
+        android:visibility="gone"
+        android:layout_width="match_parent"
+        android:layout_height="0dp" />
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/assist_orb.xml b/packages/SystemUI/res/layout/assist_orb.xml
deleted file mode 100644
index 0036ed6..0000000
--- a/packages/SystemUI/res/layout/assist_orb.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, 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.
-*/
--->
-
-<!-- Extends FrameLayout -->
-<com.android.systemui.assist.AssistOrbContainer
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <com.android.systemui.statusbar.AlphaOptimizedView
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/assist_orb_scrim_height"
-        android:layout_gravity="bottom"
-        android:id="@+id/assist_orb_scrim"
-        android:background="@drawable/assist_orb_scrim"/>
-
-    <com.android.systemui.assist.AssistOrbView
-        android:id="@+id/assist_orb"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
-
-        <ImageView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:id="@+id/search_logo"/>
-    </com.android.systemui.assist.AssistOrbView>
-
-    <com.android.systemui.statusbar.AlphaOptimizedView
-        android:id="@+id/assist_orb_navbar_scrim"
-        android:layout_height="@dimen/assist_orb_navbar_scrim_height"
-        android:layout_width="match_parent"
-        android:layout_gravity="bottom"
-        android:elevation="50dp"
-        android:outlineProvider="none"
-        android:background="@drawable/assist_orb_navbar_scrim"/>
-
-</com.android.systemui.assist.AssistOrbContainer>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/fgs_manager_app_item.xml b/packages/SystemUI/res/layout/fgs_manager_app_item.xml
new file mode 100644
index 0000000..d034f4e
--- /dev/null
+++ b/packages/SystemUI/res/layout/fgs_manager_app_item.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    Copyright (C) 2021 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:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginBottom="32dp"
+    android:orientation="horizontal"
+    android:gravity="center">
+
+  <ImageView
+      android:id="@+id/fgs_manager_app_item_icon"
+      android:layout_width="28dp"
+      android:layout_height="28dp"
+      android:layout_marginRight="12dp" />
+
+  <LinearLayout
+      android:layout_width="0dp"
+      android:layout_weight="1"
+      android:layout_height="wrap_content"
+      android:orientation="vertical">
+    <TextView
+        android:id="@+id/fgs_manager_app_item_label"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="start"
+        style="@style/TextAppearance.Dialog.Body" />
+    <TextView
+        android:id="@+id/fgs_manager_app_item_duration"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="start"
+        style="@style/FgsManagerAppDuration" />
+  </LinearLayout>
+
+  <Button
+      android:id="@+id/fgs_manager_app_item_stop_button"
+      android:layout_width="wrap_content"
+      android:layout_height="48dp"
+      android:text="@string/fgs_manager_app_item_stop_button_label"
+      android:layout_marginLeft="12dp"
+      style="?android:attr/buttonBarNeutralButtonStyle" />
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index 86e2661..4a5b637 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -156,6 +156,14 @@
                             style="@style/InternetDialog.NetworkSummary"/>
                     </LinearLayout>
 
+                    <View
+                        android:id="@+id/mobile_toggle_divider"
+                        android:layout_width="1dp"
+                        android:layout_height="28dp"
+                        android:layout_marginEnd="16dp"
+                        android:layout_gravity="center_vertical"
+                        android:background="?android:attr/textColorSecondary"/>
+
                     <FrameLayout
                         android:layout_width="@dimen/settingslib_switch_track_width"
                         android:layout_height="48dp"
@@ -177,7 +185,7 @@
                 <LinearLayout
                     android:id="@+id/turn_on_wifi_layout"
                     style="@style/InternetDialog.Network"
-                    android:layout_height="72dp"
+                    android:layout_height="@dimen/internet_dialog_wifi_network_height"
                     android:gravity="center"
                     android:clickable="false"
                     android:focusable="false">
@@ -219,7 +227,7 @@
                 <LinearLayout
                     android:id="@+id/wifi_connected_layout"
                     style="@style/InternetDialog.Network"
-                    android:layout_height="72dp"
+                    android:layout_height="@dimen/internet_dialog_wifi_network_height"
                     android:paddingStart="20dp"
                     android:paddingEnd="24dp"
                     android:background="@drawable/settingslib_switch_bar_bg_on"
@@ -241,7 +249,7 @@
                         android:orientation="vertical"
                         android:clickable="false"
                         android:layout_width="wrap_content"
-                        android:layout_height="72dp"
+                        android:layout_height="@dimen/internet_dialog_wifi_network_height"
                         android:layout_marginEnd="30dp"
                         android:layout_weight="1"
                         android:gravity="start|center_vertical">
@@ -367,8 +375,9 @@
                 android:id="@+id/done_layout"
                 android:layout_width="67dp"
                 android:layout_height="48dp"
+                android:layout_marginTop="8dp"
                 android:layout_marginEnd="24dp"
-                android:layout_marginBottom="40dp"
+                android:layout_marginBottom="34dp"
                 android:layout_gravity="end|center_vertical"
                 android:clickable="true"
                 android:focusable="true">
diff --git a/packages/SystemUI/res/layout/internet_list_item.xml b/packages/SystemUI/res/layout/internet_list_item.xml
index 868331e..f6a2136 100644
--- a/packages/SystemUI/res/layout/internet_list_item.xml
+++ b/packages/SystemUI/res/layout/internet_list_item.xml
@@ -25,7 +25,7 @@
     <LinearLayout
         android:id="@+id/wifi_list"
         style="@style/InternetDialog.Network"
-        android:layout_height="72dp"
+        android:layout_height="@dimen/internet_dialog_wifi_network_height"
         android:paddingStart="20dp"
         android:paddingEnd="24dp">
         <FrameLayout
@@ -45,7 +45,7 @@
             android:orientation="vertical"
             android:clickable="false"
             android:layout_width="wrap_content"
-            android:layout_height="72dp"
+            android:layout_height="@dimen/internet_dialog_wifi_network_height"
             android:layout_marginEnd="30dp"
             android:layout_weight="1"
             android:gravity="start|center_vertical">
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index cfba83b..8f8993f 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -17,7 +17,6 @@
 
 <com.android.systemui.statusbar.phone.KeyguardBottomAreaView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     android:id="@+id/keyguard_bottom_area"
     android:layout_height="match_parent"
     android:layout_width="match_parent"
@@ -128,7 +127,8 @@
         android:layout_height="match_parent">
 
         <include layout="@layout/keyguard_bottom_area_overlay" />
-
     </FrameLayout>
 
+    <include layout="@layout/ambient_indication"
+             android:id="@+id/ambient_indication_container" />
 </com.android.systemui.statusbar.phone.KeyguardBottomAreaView>
diff --git a/packages/SystemUI/res/layout/media_output_dialog.xml b/packages/SystemUI/res/layout/media_output_dialog.xml
index a64ef3e..4e2b4a6 100644
--- a/packages/SystemUI/res/layout/media_output_dialog.xml
+++ b/packages/SystemUI/res/layout/media_output_dialog.xml
@@ -24,24 +24,30 @@
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="96dp"
+        android:layout_height="wrap_content"
         android:gravity="start|center_vertical"
         android:paddingStart="16dp"
+        android:paddingTop="16dp"
+        android:paddingEnd="16dp"
+        android:paddingBottom="24dp"
         android:orientation="horizontal">
         <ImageView
             android:id="@+id/header_icon"
-            android:layout_width="48dp"
-            android:layout_height="48dp"
+            android:layout_width="72dp"
+            android:layout_height="72dp"
             android:importantForAccessibility="no"/>
 
         <LinearLayout
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:paddingStart="16dp"
-            android:paddingTop="20dp"
-            android:paddingBottom="24dp"
-            android:paddingEnd="24dp"
+            android:layout_height="wrap_content"
+            android:paddingStart="12dp"
             android:orientation="vertical">
+            <ImageView
+                android:id="@+id/app_source_icon"
+                android:layout_width="20dp"
+                android:layout_height="20dp"
+                android:gravity="center_vertical"
+                android:importantForAccessibility="no"/>
             <TextView
                 android:id="@+id/header_title"
                 android:layout_width="wrap_content"
@@ -51,7 +57,7 @@
                 android:maxLines="1"
                 android:textColor="?android:attr/textColorPrimary"
                 android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-                android:textSize="20sp"/>
+                android:textSize="16sp"/>
             <TextView
                 android:id="@+id/header_subtitle"
                 android:layout_width="wrap_content"
@@ -59,17 +65,12 @@
                 android:gravity="center_vertical"
                 android:ellipsize="end"
                 android:maxLines="1"
-                android:textColor="?android:attr/textColorTertiary"
+                android:textColor="?android:attr/textColorSecondary"
                 android:fontFamily="roboto-regular"
-                android:textSize="16sp"/>
+                android:textSize="14sp"/>
         </LinearLayout>
     </LinearLayout>
 
-    <View
-        android:layout_width="match_parent"
-        android:layout_height="1dp"
-        android:background="?android:attr/listDivider"/>
-
     <LinearLayout
         android:id="@+id/device_list"
         android:layout_width="match_parent"
@@ -88,10 +89,10 @@
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="16dp"
-        android:layout_marginStart="24dp"
-        android:layout_marginBottom="18dp"
-        android:layout_marginEnd="24dp"
+        android:layout_marginTop="4dp"
+        android:layout_marginStart="16dp"
+        android:layout_marginBottom="24dp"
+        android:layout_marginEnd="16dp"
         android:orientation="horizontal">
 
         <Button
@@ -110,7 +111,7 @@
 
         <Button
             android:id="@+id/done"
-            style="@style/MediaOutputRoundedOutlinedButton"
+            style="@style/MediaOutputRoundedButton"
             android:layout_width="wrap_content"
             android:layout_height="36dp"
             android:minWidth="0dp"
diff --git a/packages/SystemUI/res/layout/media_output_list_item.xml b/packages/SystemUI/res/layout/media_output_list_item.xml
index a5a7efa..2f5f8d6 100644
--- a/packages/SystemUI/res/layout/media_output_list_item.xml
+++ b/packages/SystemUI/res/layout/media_output_list_item.xml
@@ -17,26 +17,43 @@
 
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/device_container"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical">
     <FrameLayout
         android:layout_width="match_parent"
-        android:layout_height="88dp"
-        android:paddingTop="24dp"
-        android:paddingBottom="16dp"
-        android:paddingStart="24dp"
-        android:paddingEnd="8dp">
+        android:layout_height="64dp"
+        android:layout_marginStart="16dp"
+        android:layout_marginEnd="16dp"
+        android:layout_marginBottom="12dp">
+        <FrameLayout
+            android:id="@+id/item_layout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@drawable/media_output_item_background"
+            android:layout_gravity="center_vertical|start">
+            <SeekBar
+                android:id="@+id/volume_seekbar"
+                android:splitTrack="false"
+                android:visibility="gone"
+                android:paddingStart="0dp"
+                android:paddingEnd="0dp"
+                android:progressDrawable="@drawable/media_output_dialog_seekbar_background"
+                android:thumb="@null"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"/>
+        </FrameLayout>
 
         <FrameLayout
-            android:layout_width="48dp"
-            android:layout_height="48dp"
+            android:layout_width="56dp"
+            android:layout_height="64dp"
             android:layout_gravity="center_vertical|start">
             <ImageView
                 android:id="@+id/title_icon"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
+                android:layout_width="24dp"
+                android:layout_height="24dp"
                 android:layout_gravity="center"/>
         </FrameLayout>
 
@@ -45,55 +62,46 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical|start"
-            android:layout_marginStart="64dp"
+            android:layout_marginStart="56dp"
             android:ellipsize="end"
             android:maxLines="1"
-            android:textColor="?android:attr/textColorPrimary"
+            android:textColor="?androidprv:attr/colorAccentPrimaryVariant"
             android:textSize="16sp"/>
 
         <RelativeLayout
             android:id="@+id/two_line_layout"
             android:layout_width="wrap_content"
+            android:layout_gravity="center_vertical|start"
             android:layout_height="48dp"
-            android:layout_marginStart="48dp">
+            android:layout_marginStart="56dp">
             <TextView
                 android:id="@+id/two_line_title"
+                android:gravity="center_vertical"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginStart="16dp"
-                android:layout_marginEnd="48dp"
                 android:ellipsize="end"
                 android:maxLines="1"
-                android:textColor="?android:attr/textColorPrimary"
+                android:textColor="?androidprv:attr/colorAccentPrimaryVariant"
                 android:textSize="16sp"/>
             <TextView
                 android:id="@+id/subtitle"
+                android:layout_gravity="center_vertical"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginStart="16dp"
-                android:layout_marginEnd="15dp"
                 android:layout_marginTop="4dp"
                 android:layout_alignParentBottom="true"
                 android:ellipsize="end"
                 android:maxLines="1"
-                android:textColor="?android:attr/textColorSecondary"
+                android:textColor="?androidprv:attr/colorAccentPrimaryVariant"
                 android:textSize="14sp"
                 android:fontFamily="roboto-regular"
                 android:visibility="gone"/>
-            <SeekBar
-                android:id="@+id/volume_seekbar"
-                android:layout_marginTop="16dp"
-                android:layout_marginEnd="8dp"
-                style="@*android:style/Widget.DeviceDefault.SeekBar"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_alignParentBottom="true"/>
             <ImageView
                 android:id="@+id/add_icon"
                 android:layout_width="24dp"
                 android:layout_height="24dp"
                 android:layout_gravity="right"
-                android:layout_marginEnd="24dp"
+                android:layout_marginEnd="16dp"
                 android:layout_alignParentRight="true"
                 android:src="@drawable/ic_add"
                 android:tint="?android:attr/colorAccent"
@@ -103,30 +111,33 @@
                 android:layout_width="24dp"
                 android:layout_height="24dp"
                 android:layout_gravity="right"
-                android:layout_marginEnd="24dp"
+                android:layout_marginEnd="16dp"
                 android:layout_alignParentRight="true"
                 android:button="@drawable/ic_check_box"
                 android:visibility="gone"
-                />
+            />
         </RelativeLayout>
 
         <ProgressBar
             android:id="@+id/volume_indeterminate_progress"
-            style="@*android:style/Widget.Material.ProgressBar.Horizontal"
-            android:layout_width="258dp"
-            android:layout_height="18dp"
-            android:layout_marginStart="64dp"
-            android:layout_marginTop="28dp"
+            style="?android:attr/progressBarStyleSmallTitle"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            android:layout_marginEnd="16dp"
             android:indeterminate="true"
+            android:layout_gravity="right|center"
             android:indeterminateOnly="true"
             android:visibility="gone"/>
-    </FrameLayout>
 
-    <View
-        android:id="@+id/bottom_divider"
-        android:layout_width="match_parent"
-        android:layout_height="1dp"
-        android:layout_gravity="bottom"
-        android:background="?android:attr/listDivider"
-        android:visibility="gone"/>
+        <ImageView
+            android:id="@+id/media_output_item_status"
+            android:layout_width="24dp"
+            android:layout_height="24dp"
+            android:layout_marginEnd="16dp"
+            android:indeterminate="true"
+            android:layout_gravity="right|center"
+            android:indeterminateOnly="true"
+            android:importantForAccessibility="no"
+            android:visibility="gone"/>
+    </FrameLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/privacy_dialog.xml b/packages/SystemUI/res/layout/privacy_dialog.xml
index ee4530c..9368a6a 100644
--- a/packages/SystemUI/res/layout/privacy_dialog.xml
+++ b/packages/SystemUI/res/layout/privacy_dialog.xml
@@ -22,10 +22,9 @@
     android:layout_height="wrap_content"
     android:layout_marginStart="@dimen/ongoing_appops_dialog_side_margins"
     android:layout_marginEnd="@dimen/ongoing_appops_dialog_side_margins"
-    android:layout_marginTop="8dp"
     android:orientation="vertical"
     android:paddingBottom="8dp"
-    android:paddingTop="12dp"
+    android:paddingTop="8dp"
     android:paddingHorizontal="@dimen/ongoing_appops_dialog_side_padding"
     android:background="@drawable/qs_dialog_bg"
 />
diff --git a/packages/SystemUI/res/layout/qs_user_detail.xml b/packages/SystemUI/res/layout/qs_user_detail.xml
index 91d3a53..1aec296 100644
--- a/packages/SystemUI/res/layout/qs_user_detail.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail.xml
@@ -22,6 +22,6 @@
         xmlns:sysui="http://schemas.android.com/apk/res-auto"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        sysui:verticalSpacing="4dp"
+        sysui:verticalSpacing="20dp"
         sysui:horizontalSpacing="4dp"
         style="@style/UserDetailView" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_user_detail_item.xml b/packages/SystemUI/res/layout/qs_user_detail_item.xml
index cc6c5d3..91b11fc 100644
--- a/packages/SystemUI/res/layout/qs_user_detail_item.xml
+++ b/packages/SystemUI/res/layout/qs_user_detail_item.xml
@@ -24,8 +24,6 @@
         android:layout_height="wrap_content"
         android:orientation="vertical"
         android:gravity="top|center_horizontal"
-        android:paddingTop="16dp"
-        android:minHeight="112dp"
         android:clipChildren="false"
         android:clipToPadding="false"
         android:focusable="true"
diff --git a/packages/SystemUI/res/layout/qs_user_dialog_content.xml b/packages/SystemUI/res/layout/qs_user_dialog_content.xml
index 9495ee6..355df2c 100644
--- a/packages/SystemUI/res/layout/qs_user_dialog_content.xml
+++ b/packages/SystemUI/res/layout/qs_user_dialog_content.xml
@@ -15,75 +15,19 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License.
   -->
-
-<androidx.constraintlayout.widget.ConstraintLayout
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:sysui="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:padding="24dp"
-    android:layout_marginStart="16dp"
-    android:layout_marginEnd="16dp"
->
-    <TextView
-        android:id="@+id/title"
-        android:layout_height="wrap_content"
-        android:layout_width="0dp"
-        android:textAlignment="center"
-        android:text="@string/qs_user_switch_dialog_title"
-        android:textAppearance="@style/TextAppearance.QSDialog.Title"
-        android:layout_marginBottom="32dp"
-        sysui:layout_constraintTop_toTopOf="parent"
-        sysui:layout_constraintStart_toStartOf="parent"
-        sysui:layout_constraintEnd_toEndOf="parent"
-        sysui:layout_constraintBottom_toTopOf="@id/grid"
-        />
-
+    >
     <com.android.systemui.qs.PseudoGridView
-        android:id="@+id/grid"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="28dp"
-        sysui:verticalSpacing="4dp"
-        sysui:horizontalSpacing="4dp"
-        sysui:fixedChildWidth="80dp"
-        sysui:layout_constraintTop_toBottomOf="@id/title"
-        sysui:layout_constraintStart_toStartOf="parent"
-        sysui:layout_constraintEnd_toEndOf="parent"
-        sysui:layout_constraintBottom_toTopOf="@id/barrier"
-    />
-
-    <androidx.constraintlayout.widget.Barrier
-        android:id="@+id/barrier"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        sysui:barrierDirection="top"
-        sysui:constraint_referenced_ids="settings,done"
+            android:id="@+id/grid"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            sysui:verticalSpacing="20dp"
+            sysui:horizontalSpacing="4dp"
+            sysui:fixedChildWidth="80dp"
         />
-
-    <Button
-        android:id="@+id/settings"
-        android:layout_width="wrap_content"
-        android:layout_height="48dp"
-        android:text="@string/quick_settings_more_user_settings"
-        sysui:layout_constraintTop_toBottomOf="@id/barrier"
-        sysui:layout_constraintBottom_toBottomOf="parent"
-        sysui:layout_constraintStart_toStartOf="parent"
-        sysui:layout_constraintEnd_toStartOf="@id/done"
-        sysui:layout_constraintHorizontal_chainStyle="spread_inside"
-        style="@style/Widget.QSDialog.Button.BorderButton"
-        />
-
-    <Button
-        android:id="@+id/done"
-        android:layout_width="wrap_content"
-        android:layout_height="48dp"
-        android:text="@string/quick_settings_done"
-        sysui:layout_constraintTop_toBottomOf="@id/barrier"
-        sysui:layout_constraintBottom_toBottomOf="parent"
-        sysui:layout_constraintStart_toEndOf="@id/settings"
-        sysui:layout_constraintEnd_toEndOf="parent"
-        style="@style/Widget.QSDialog.Button"
-        />
-
-</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index b4c9a93..2290964 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -128,9 +128,6 @@
             systemui:layout_constraintEnd_toEndOf="parent"
         />
 
-        <include layout="@layout/ambient_indication"
-            android:id="@+id/ambient_indication_container" />
-
         <include layout="@layout/photo_preview_overlay" />
 
         <include
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 4015762..f2d27c4 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Die program of jou organisasie laat nie toe dat skermkiekies geneem word nie"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Wysig"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Wysig skermkiekie"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Deel skermskoot"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Vang meer vas"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Maak skermkiekie toe"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Skermkiekievoorskou"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Foon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Stembystand"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Beursie"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Ontsluit"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Toestel is gesluit"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skandeer tans gesig"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ontsluit om te gebruik"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Kon nie jou kaarte kry nie; probeer later weer"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Sluitskerminstellings"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuigmodus"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Jy sal nie jou volgende wekker <xliff:g id="WHEN">%1$s</xliff:g> hoor nie"</string>
diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml
index c20d01e..036ba10 100644
--- a/packages/SystemUI/res/values-af/strings_tv.xml
+++ b/packages/SystemUI/res/values-af/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofoon aktief"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s het toegang tot jou mikrofoon"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is gekoppel"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is ontkoppel"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-af/tiles_states_strings.xml b/packages/SystemUI/res/values-af/tiles_states_strings.xml
index 5ce5340..c7e76180 100644
--- a/packages/SystemUI/res/values-af/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-af/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Af"</item>
     <item msgid="6866424167599381915">"Aan"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Onbeskikbaar"</item>
     <item msgid="2710157085538036590">"Af"</item>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 723f766..b71cf7a 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ቅጽበታዊ ገጽ እይታዎችን ማንሳት በመተግበሪያው ወይም በእርስዎ ድርጅት አይፈቀድም"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"አርትዕ ያድርጉ"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"ቅጽበታዊ ገጽ ዕይታን አርትዕ ያድርጉ"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"ቅጽበታዊ ገጽ እይታን ያጋሩ"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"ተጨማሪ ይቅረጹ"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ቅጽበታዊ ገጽ ዕይታን አሰናብት"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"የቅጽበታዊ ገጽ ዕይታ ቅድመ-ዕይታ"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ስልክ"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"የድምጽ እርዳታ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"የኪስ ቦርሳ"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"ክፈት"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"መሣሪያ ተቆልፏል"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"የቅኝት ፊት"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ለማየት ይክፈቱ"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"የእርስዎን ካርዶች ማግኘት ላይ ችግር ነበር፣ እባክዎ ቆይተው እንደገና ይሞክሩ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"የገጽ መቆለፊያ ቅንብሮች"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"የስራ መገለጫ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"የአውሮፕላን ሁነታ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"የእርስዎን ቀጣይ ማንቂያ <xliff:g id="WHEN">%1$s</xliff:g> አይሰሙም"</string>
diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
index 39429e4..3b90ea0 100644
--- a/packages/SystemUI/res/values-am/strings_tv.xml
+++ b/packages/SystemUI/res/values-am/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"ማይክራፎን ንቁ ነው"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s የእርስዎን ማይክራፎን ደርሶበታል"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ተያይዟል"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ተቋርቷል"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"በ<xliff:g id="VPN_APP">%1$s</xliff:g> በኩል"</string>
diff --git a/packages/SystemUI/res/values-am/tiles_states_strings.xml b/packages/SystemUI/res/values-am/tiles_states_strings.xml
index 0a53d20..e5be860 100644
--- a/packages/SystemUI/res/values-am/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-am/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"ጠፍቷል"</item>
     <item msgid="6866424167599381915">"በርቷል"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"አይገኝም"</item>
     <item msgid="2710157085538036590">"ጠፍቷል"</item>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index a163a9b..4141969 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"يحظر التطبيق أو تحظر مؤسستك التقاط لقطات شاشة"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"تعديل"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"تعديل لقطة الشاشة"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"مشاركة لقطة الشاشة"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"التقاط المزيد من المحتوى"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"إغلاق لقطة الشاشة"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"معاينة لقطة الشاشة"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"الهاتف"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"المساعد الصوتي"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"المحفظة"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"فتح القفل"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"الجهاز مُقفل."</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"مسح الوجه"</string>
@@ -477,6 +478,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"فتح القفل للاستخدام"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"حدثت مشكلة أثناء الحصول على البطاقات، يُرجى إعادة المحاولة لاحقًا."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"إعدادات شاشة القفل"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"الملف الشخصي للعمل"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"وضع الطيران"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"لن تسمع المنبّه القادم في <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml
index 13f23f0..f33d036 100644
--- a/packages/SystemUI/res/values-ar/strings_tv.xml
+++ b/packages/SystemUI/res/values-ar/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"الميكروفون نشط"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"‏تمكن %1$s من الوصول إلى الميكروفون الخاص بك."</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"‏شبكة VPN متصلة."</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"‏شبكة VPN غير متصلة."</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"عبر <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ar/tiles_states_strings.xml b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
index 90baf04..e2b8632 100644
--- a/packages/SystemUI/res/values-ar/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ar/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"الميزة غير مفعّلة"</item>
     <item msgid="6866424167599381915">"الميزة مفعّلة"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"الميزة غير متاحة"</item>
     <item msgid="2710157085538036590">"الميزة غير مفعّلة"</item>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index a36532a..7c7d95b 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ফ\'ন"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"কণ্ঠধ্বনিৰে সহায়"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ৱালেট"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"আনলক কৰক"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ডিভাইচটো লক হৈ আছে"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"চেহেৰা স্কেন কৰি থকা হৈছে"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ব্যৱহাৰ কৰিবলৈ আনলক কৰক"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"আপোনাৰ কাৰ্ড লাভ কৰোঁতে এটা সমস্যা হৈছে, অনুগ্ৰহ কৰি পাছত পুনৰ চেষ্টা কৰক"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"লক স্ক্ৰীনৰ ছেটিং"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"এয়াৰপ্লেইন ম\'ড"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"আপুনি আপোনাৰ পিছৰটো এলাৰ্ম <xliff:g id="WHEN">%1$s</xliff:g> বজাত শুনা নাপাব"</string>
diff --git a/packages/SystemUI/res/values-as/strings_tv.xml b/packages/SystemUI/res/values-as/strings_tv.xml
index 733e2e6..33129ec 100644
--- a/packages/SystemUI/res/values-as/strings_tv.xml
+++ b/packages/SystemUI/res/values-as/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"মাইক্ৰ’ফ’ন সক্ৰিয় কৰা আছে"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$sএ আপোনাৰ মাইক্ৰ’ফ’ন এক্সেছ কৰিছে"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"ভিপিএন সংযোগ হৈ আছে"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ভিপিএনৰ সংযোগ বিচ্ছিন্ন হৈছে"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>ৰ জৰিয়তে"</string>
diff --git a/packages/SystemUI/res/values-as/tiles_states_strings.xml b/packages/SystemUI/res/values-as/tiles_states_strings.xml
index fa333df..43957f4 100644
--- a/packages/SystemUI/res/values-as/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-as/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"অফ আছে"</item>
     <item msgid="6866424167599381915">"অন কৰা আছে"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"উপলব্ধ নহয়"</item>
     <item msgid="2710157085538036590">"অফ আছে"</item>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index 5a53dd8..8e27b0f 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Skrinşot çəkməyə tətbiq və ya təşkilat tərəfindən icazə verilmir"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Redaktə edin"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Skrinşota düzəliş edin"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Skrinşotu paylaşın"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Genişləndirin"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ekran şəklini ötürün"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekran şəklinə önbaxış"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Səs Yardımçısı"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Pulqabı"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Kiliddən çıxarın"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Cihaz kilidlənib"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Üzün skan edilməsi"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"İstifadə etmək üçün kiliddən çıxarın"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Kartların əldə edilməsində problem oldu, sonra yenidən cəhd edin"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Kilid ekranı ayarları"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Təyyarə rejimi"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> zaman növbəti xəbərdarlığınızı eşitməyəcəksiniz"</string>
diff --git a/packages/SystemUI/res/values-az/strings_tv.xml b/packages/SystemUI/res/values-az/strings_tv.xml
index cd8b46c..703124c 100644
--- a/packages/SystemUI/res/values-az/strings_tv.xml
+++ b/packages/SystemUI/res/values-az/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon Aktivdir"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s mikrofona daxil olub"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN qoşulub"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ayrılıb"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> vasitəsilə"</string>
diff --git a/packages/SystemUI/res/values-az/tiles_states_strings.xml b/packages/SystemUI/res/values-az/tiles_states_strings.xml
index 1a3a2dc..4baea08 100644
--- a/packages/SystemUI/res/values-az/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-az/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Deaktiv"</item>
     <item msgid="6866424167599381915">"Aktiv"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Əlçatan deyil"</item>
     <item msgid="2710157085538036590">"Deaktiv"</item>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index db3d917..6d5e75a 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili organizacija ne dozvoljavaju pravljenje snimaka ekrana"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Izmeni"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Izmenite snimak ekrana"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Delite snimak ekrana"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Snimite još"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Odbacite snimak ekrana"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimka ekrana"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Novčanik"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Otključajte"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skeniranje lica"</string>
@@ -468,6 +469,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključaj radi korišćenja"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Došlo je do problema pri preuzimanju kartica. Probajte ponovo kasnije"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Podešavanja zaključanog ekrana"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Režim rada u avionu"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sledeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
index 31a37db..27e22d8 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon je aktivan"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacija %1$s je pristupila mikrofonu"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je povezan"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Veza sa VPN-om je prekinuta"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Preko: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
index 5622a82..90b8cce 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Isključeno"</item>
     <item msgid="6866424167599381915">"Uključeno"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Nedostupno"</item>
     <item msgid="2710157085538036590">"Isključeno"</item>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 262752c..e98c498 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Рабіць здымкі экрана не дазваляе праграма ці ваша арганізацыя"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Змяніць"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Змяніць здымак экрана"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Абагуліць здымак экрана"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Зняць больш"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Адхіліць здымак экрана"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Перадпрагляд здымка экрана"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Тэлефон"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Галасавая дапамога"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Кашалёк"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Разблакiраваць"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Прылада заблакіравана"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Сканіраванне твару"</string>
@@ -285,7 +286,7 @@
     <string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Уключыць у <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"Да <xliff:g id="TIME">%s</xliff:g>"</string>
     <string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Цёмная тэма"</string>
-    <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Эканомія зараду"</string>
+    <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Энергазберажэнне"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Уключана ўвечары"</string>
     <string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Да ўсходу сонца"</string>
     <string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Уключана ў <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -471,6 +472,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Разблакіраваць для выкарыстання"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Узнікла праблема з загрузкай вашых карт. Паўтарыце спробу пазней"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Налады экрана блакіроўкі"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Працоўны профіль"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Рэжым палёту"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Вы не пачуеце наступны будзільнік <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -546,7 +551,7 @@
       <item quantity="many">%d хвілін</item>
       <item quantity="other">%d хвіліны</item>
     </plurals>
-    <string name="battery_detail_switch_title" msgid="6940976502957380405">"Эканомія зараду"</string>
+    <string name="battery_detail_switch_title" msgid="6940976502957380405">"Рэжым энергазберажэння"</string>
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Кнопка <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
     <string name="keyboard_key_back" msgid="4185420465469481999">"Назад"</string>
diff --git a/packages/SystemUI/res/values-be/strings_tv.xml b/packages/SystemUI/res/values-be/strings_tv.xml
index 410c120..4de4de4 100644
--- a/packages/SystemUI/res/values-be/strings_tv.xml
+++ b/packages/SystemUI/res/values-be/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Мікрафон актыўны"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Праграма \"%1$s\" атрымала доступ да мікрафона"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN падключаны"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN адключаны"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Праз <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-be/tiles_states_strings.xml b/packages/SystemUI/res/values-be/tiles_states_strings.xml
index b70a813..4ad97d2 100644
--- a/packages/SystemUI/res/values-be/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-be/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Выключана"</item>
     <item msgid="6866424167599381915">"Уключана"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Недаступна"</item>
     <item msgid="2710157085538036590">"Выключана"</item>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 8d090e4..951714e 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласова помощ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Портфейл"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Отключване"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Устройството е заключено"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Извършва се сканиране на лице"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Отключване с цел използване"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"При извличането на картите ви възникна проблем. Моля, опитайте отново по-късно"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Настройки за заключения екран"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Потребителски профил в Work"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Самолетен режим"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Няма да чуете следващия си будилник в <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
index 981ab95..5db6ac8 100644
--- a/packages/SystemUI/res/values-bg/strings_tv.xml
+++ b/packages/SystemUI/res/values-bg/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Микрофонът е активен"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s осъществи достъп до микрофона ви"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN е свързана"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Връзката с VPN е прекратена"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Чрез <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-bg/tiles_states_strings.xml b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
index 85d9393..e7cc889 100644
--- a/packages/SystemUI/res/values-bg/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bg/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Изкл."</item>
     <item msgid="6866424167599381915">"Вкл."</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Не е налице"</item>
     <item msgid="2710157085538036590">"Изкл."</item>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index ac6aaeb..217f9e3 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"এই অ্যাপ বা আপনার প্রতিষ্ঠান স্ক্রিনশট নেওয়ার অনুমতি দেয়নি"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"এডিট করুন"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"স্ক্রিনশট এডিট করুন"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"স্ক্রিনশট শেয়ার করুন"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"আরও বেশি ক্যাপচার করুন"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"স্ক্রিনশট বাতিল করুন"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"স্ক্রিনশটের প্রিভিউ"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ফোন"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ভয়েস সহায়তা"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ওয়ালেট"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"আনলক করুন"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ডিভাইস লক করা আছে"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ফেস স্ক্যান করা হচ্ছে"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ব্যবহার করতে আনলক করুন"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"আপনার কার্ড সংক্রান্ত তথ্য পেতে সমস্যা হয়েছে, পরে আবার চেষ্টা করুন"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"লক স্ক্রিন সেটিংস"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"কাজের প্রোফাইল"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"বিমান মোড"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"আপনি আপনার পরবর্তী <xliff:g id="WHEN">%1$s</xliff:g> অ্যালার্ম শুনতে পাবেন না"</string>
diff --git a/packages/SystemUI/res/values-bn/strings_tv.xml b/packages/SystemUI/res/values-bn/strings_tv.xml
index 5d252b1..79391f4 100644
--- a/packages/SystemUI/res/values-bn/strings_tv.xml
+++ b/packages/SystemUI/res/values-bn/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"মাইক্রোফোন চালু আছে"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s আপনার ডিভাইসের মাইক্রোফোন অ্যাক্সেস করেছে"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN কানেক্ট করা হয়েছে"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ডিসকানেক্ট করা হয়েছে"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-এর মাধ্যমে"</string>
diff --git a/packages/SystemUI/res/values-bn/tiles_states_strings.xml b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
index 631446d..584de5e 100644
--- a/packages/SystemUI/res/values-bn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bn/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"বন্ধ আছে"</item>
     <item msgid="6866424167599381915">"চালু আছে"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"উপলভ্য নেই"</item>
     <item msgid="2710157085538036590">"বন্ধ আছে"</item>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 4680da9..efcb4d4 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ova aplikacija ili vaša organizacija ne dozvoljavaju snimanje ekrana"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Uredite"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Uredite snimak ekrana"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Dijeljenje snimka ekrana"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Snimite više"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Odbacite snimak ekrana"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimka ekrana"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Novčanik"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Otključaj"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skeniranje lica"</string>
@@ -468,6 +469,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da koristite"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Došlo je do problema prilikom preuzimanja vaših kartica. Pokušajte ponovo kasnije"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključavanja ekrana"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil za posao"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u avionu"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sljedeći alarm u <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-bs/strings_tv.xml b/packages/SystemUI/res/values-bs/strings_tv.xml
index 341c125..626938f 100644
--- a/packages/SystemUI/res/values-bs/strings_tv.xml
+++ b/packages/SystemUI/res/values-bs/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon je aktivan"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacija %1$s je pristupila vašem mikrofonu"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je povezan"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Veza s VPN-om je prekinuta"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-bs/tiles_states_strings.xml b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
index 5622a82..90b8cce 100644
--- a/packages/SystemUI/res/values-bs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-bs/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Isključeno"</item>
     <item msgid="6866424167599381915">"Uključeno"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Nedostupno"</item>
     <item msgid="2710157085538036590">"Isključeno"</item>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 778a52c..8ddc456 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'aplicació o la teva organització no permeten fer captures de pantalla"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Edita"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Edita la captura de pantalla"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Comparteix la captura de pantalla"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Captura més"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignora la captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Previsualització de la captura de pantalla"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telèfon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistència per veu"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Cartera"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloqueja"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositiu bloquejat"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"S\'està escanejant la cara"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloqueja per utilitzar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Hi ha hagut un problema en obtenir les teves targetes; torna-ho a provar més tard"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuració de la pantalla de bloqueig"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de treball"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode d\'avió"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> no sentiràs la pròxima alarma"</string>
diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml
index 6a28c83..3985f09 100644
--- a/packages/SystemUI/res/values-ca/strings_tv.xml
+++ b/packages/SystemUI/res/values-ca/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Micròfon actiu"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ha accedit al teu micròfon"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN està connectada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN està desconnectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Mitjançant <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ca/tiles_states_strings.xml b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
index ddb9dc8..27bfb9c 100644
--- a/packages/SystemUI/res/values-ca/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ca/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Desactivat"</item>
     <item msgid="6866424167599381915">"Activat"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"No disponible"</item>
     <item msgid="2710157085538036590">"Desactivat"</item>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 3c9a9c4..55c5333 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikace nebo organizace zakazuje pořizování snímků obrazovky"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Upravit"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Upravit snímek obrazovky"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Sdílet snímek obrazovky"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Zvětšit záběr snímku"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Zavřít snímek obrazovky"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Náhled snímku obrazovky"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hlasová asistence"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Peněženka"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Odemknout"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Zařízení uzamčeno"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skenování obličeje"</string>
@@ -471,6 +472,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odemknout a použít"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Při načítání karet došlo k problému, zkuste to později"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavení obrazovky uzamčení"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Pracovní profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Režim Letadlo"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Svůj další budík <xliff:g id="WHEN">%1$s</xliff:g> neuslyšíte"</string>
diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml
index 115c875..7fe2cdf 100644
--- a/packages/SystemUI/res/values-cs/strings_tv.xml
+++ b/packages/SystemUI/res/values-cs/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon je aktivní"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikace %1$s použila mikrofon"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Síť VPN je připojena"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Síť VPN je odpojena"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Přes <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-cs/tiles_states_strings.xml b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
index 427770d..ee1f8fb8 100644
--- a/packages/SystemUI/res/values-cs/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-cs/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Vyp"</item>
     <item msgid="6866424167599381915">"Zap"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Nedostupné"</item>
     <item msgid="2710157085538036590">"Vyp"</item>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 9fa3baec..2420c7f 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller din organisation tillader ikke, at du tager screenshots"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Rediger"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Rediger screenshot"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Del screenshottet"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Medtag mere"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Luk screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Forhåndsvisning af screenshot"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Taleassistent"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Lås op"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Enheden er låst"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanner ansigt"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås op for at bruge"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Dine kort kunne ikke hentes. Prøv igen senere."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lås skærmindstillinger"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Arbejdsprofil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flytilstand"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Du vil ikke kunne høre din næste alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml
index af48946..eb61128 100644
--- a/packages/SystemUI/res/values-da/strings_tv.xml
+++ b/packages/SystemUI/res/values-da/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofonen er slået til"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s fik adgang til din mikrofon"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tilsluttet"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er afbrudt"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-da/tiles_states_strings.xml b/packages/SystemUI/res/values-da/tiles_states_strings.xml
index 6c7d4d9..770c2ed 100644
--- a/packages/SystemUI/res/values-da/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-da/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Fra"</item>
     <item msgid="6866424167599381915">"Til"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Ikke tilgængelig"</item>
     <item msgid="2710157085538036590">"Fra"</item>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 7241836..61d489c 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonnummer"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Sprachassistent"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Entsperren"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Gerät gesperrt"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Gesicht wird gescannt"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Zum Verwenden entsperren"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Beim Abrufen deiner Karten ist ein Fehler aufgetreten – bitte versuch es später noch einmal"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Einstellungen für den Sperrbildschirm"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Arbeitsprofil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flugmodus"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Lautloser Weckruf <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml
index e8e8dcd..ec32c74 100644
--- a/packages/SystemUI/res/values-de/strings_tv.xml
+++ b/packages/SystemUI/res/values-de/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon aktiv"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s hat auf dein Mikrofon zugegriffen"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ist verbunden"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ist nicht verbunden"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Über <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-de/tiles_states_strings.xml b/packages/SystemUI/res/values-de/tiles_states_strings.xml
index 19ceead..50d0ed5 100644
--- a/packages/SystemUI/res/values-de/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-de/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Aus"</item>
     <item msgid="6866424167599381915">"An"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Nicht verfügbar"</item>
     <item msgid="2710157085538036590">"Aus"</item>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 8ca961a..0bd3940 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Η λήψη στιγμιότυπων οθόνης δεν επιτρέπεται από την εφαρμογή ή τον οργανισμό σας"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Επεξεργασία"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Επεξεργασία στιγμιότυπου οθόνης"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Κοινοποίηση στιγμιότυπου οθόνης"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Λήψη περισσότερων"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Παράβλεψη στιγμιότυπου οθόνης"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Προεπισκόπηση στιγμιότυπου οθόνης"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Τηλέφωνο"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Φωνητική υποβοήθηση"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Πορτοφόλι"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Ξεκλείδωμα"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Η συσκευή κλειδώθηκε"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Σάρωση προσώπου"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ξεκλείδωμα για χρήση"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Παρουσιάστηκε πρόβλημα με τη λήψη των καρτών σας. Δοκιμάστε ξανά αργότερα"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ρυθμίσεις κλειδώματος οθόνης"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Προφίλ εργασίας"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Λειτουργία πτήσης"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Δεν θα ακούσετε το επόμενο ξυπνητήρι σας <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml
index 01def2b..87ef296 100644
--- a/packages/SystemUI/res/values-el/strings_tv.xml
+++ b/packages/SystemUI/res/values-el/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Ενεργό μικρόφωνο"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Πραγματοποιήθηκε πρόσβαση στο μικρόφωνό σας από το %1$s"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Το VPN συνδέθηκε"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Το VPN αποσυνδέθηκε"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Μέσω <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-el/tiles_states_strings.xml b/packages/SystemUI/res/values-el/tiles_states_strings.xml
index 1dbaaa6..76f98f5 100644
--- a/packages/SystemUI/res/values-el/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-el/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Ανενεργό"</item>
     <item msgid="6866424167599381915">"Ενεργό"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Μη διαθέσιμο"</item>
     <item msgid="2710157085538036590">"Ανενεργό"</item>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index c1950be..9807774 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
index 08fc8a6..09401c3 100644
--- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Microphone active"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accessed your microphone"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
index 0496502..2215f2d 100644
--- a/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Off"</item>
     <item msgid="6866424167599381915">"On"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Unavailable"</item>
     <item msgid="2710157085538036590">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 393289e..246d580 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings_tv.xml b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
index 08fc8a6..09401c3 100644
--- a/packages/SystemUI/res/values-en-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Microphone active"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accessed your microphone"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
index 0496502..2215f2d 100644
--- a/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Off"</item>
     <item msgid="6866424167599381915">"On"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Unavailable"</item>
     <item msgid="2710157085538036590">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index c1950be..9807774 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
index 08fc8a6..09401c3 100644
--- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Microphone active"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accessed your microphone"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
index 0496502..2215f2d 100644
--- a/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Off"</item>
     <item msgid="6866424167599381915">"On"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Unavailable"</item>
     <item msgid="2710157085538036590">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index c1950be..9807774 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Phone"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Unlock"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Device locked"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanning face"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Unlock to use"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"There was a problem getting your cards. Please try again later."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lock screen settings"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Work profile"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Aeroplane mode"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"You won\'t hear your next alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
index 08fc8a6..09401c3 100644
--- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Microphone active"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accessed your microphone"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN is connected"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN is disconnected"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
index 0496502..2215f2d 100644
--- a/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Off"</item>
     <item msgid="6866424167599381915">"On"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Unavailable"</item>
     <item msgid="2710157085538036590">"Off"</item>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 44471bd..95d8074 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -107,6 +107,7 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‎‏‏‏‎‎‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‎‎‎‏‎‏‏‎Phone‎‏‎‎‏‎"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎‎‎‏‏‏‎‎Voice Assist‎‏‎‎‏‎"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‏‎‏‏‏‏‎‎‏‏‎Wallet‎‏‎‎‏‎"</string>
+    <string name="accessibility_qr_code_scanner_button" msgid="7521277927692910795">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‎‎‎‎‎‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎QR Code Scanner‎‏‎‎‏‎"</string>
     <string name="accessibility_unlock_button" msgid="122785427241471085">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‎‏‏‏‎‎‎‏‎‏‏‎‎‏‎‎‎‎‎‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‎‏‎Unlock‎‏‎‎‏‎"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‏‏‏‎‎‎‎‏‏‎‎‎‎‎‏‏‏‏‎‎‎‏‎‎‎‏‎‏‏‏‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‎‏‏‏‏‏‏‎Device locked‎‏‎‎‏‎"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‎‏‏‏‏‎‏‏‏‏‏‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‎‏‎‎‎‎‏‎‏‏‎Scanning face‎‏‎‎‏‎"</string>
@@ -464,6 +465,8 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‏‏‎‏‎‏‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‎Unlock to use‎‏‎‎‏‎"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‏‎‏‏‎There was a problem getting your cards, please try again later‎‏‎‎‏‎"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‏‎‎‏‎‎Lock screen settings‎‏‎‎‏‎"</string>
+    <string name="qr_code_scanner_title" msgid="1598912458255252498">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‎‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‏‎‎‏‎‎Scan QR‎‏‎‎‏‎"</string>
+    <string name="qr_code_scanner_description" msgid="7452098243938659945">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‏‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‏‎‏‏‏‎‎‏‏‎‏‎‎‏‎Click to scan a QR code‎‏‎‎‏‎"</string>
     <string name="status_bar_work" msgid="5238641949837091056">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‎‎Work profile‎‏‎‎‏‎"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎Airplane mode‎‏‎‎‏‎"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎You won\'t hear your next alarm ‎‏‎‎‏‏‎<xliff:g id="WHEN">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings_tv.xml b/packages/SystemUI/res/values-en-rXC/strings_tv.xml
index c030833..21b0ef5 100644
--- a/packages/SystemUI/res/values-en-rXC/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‎‎‎‏‏‎‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‎‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‎‎‎‎Microphone Active‎‏‎‎‏‎"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎%1$s accessed your microphone‎‏‎‎‏‎"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‎‏‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‎‏‏‎‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‎‎VPN is connected‎‏‎‎‏‎"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‏‎‎‎‏‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‎‏‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎VPN is disconnected‎‏‎‎‏‎"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‎‎‎‎‎‎‎‎‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‎‎Via ‎‏‎‎‏‏‎<xliff:g id="VPN_APP">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
index 3bc03c0..2432ea3 100644
--- a/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/tiles_states_strings.xml
@@ -151,6 +151,11 @@
     <item msgid="7571394439974244289">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎Off‎‏‎‎‏‎"</item>
     <item msgid="6866424167599381915">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‏‏‎‎‎‎‎‏‏‎‎‏‏‎‏‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‎‏‏‎‏‏‎On‎‏‎‎‏‎"</item>
   </string-array>
+  <string-array name="tile_states_qr_code_scanner">
+    <item msgid="7435143266149257618">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‎‎‎‎‏‏‏‏‎‏‏‎‏‏‎‏‎‎‎‏‏‎‎‏‎‎‏‎‎Unavailable‎‏‎‎‏‎"</item>
+    <item msgid="3301403109049256043">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‎‏‎‏‏‎Off‎‏‎‎‏‎"</item>
+    <item msgid="8878684975184010135">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‎‏‏‎‏‏‎‎‏‏‏‏‎‎‎‏‏‎‎‏‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‏‏‎‏‏‏‎‎‏‎‏‏‏‎On‎‏‎‎‏‎"</item>
+  </string-array>
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‎‏‎‎‎‎‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‎‏‎‎‏‏‏‎‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎Unavailable‎‏‎‎‏‎"</item>
     <item msgid="2710157085538036590">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‏‏‎‎‎‎‎‏‎‏‎‏‎‎‎‎‏‎‎‎‎‎‎‎‎‏‎‏‎‏‎‏‏‎‏‏‎‏‏‏‎‎Off‎‏‎‎‏‎"</item>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index caa77dd..bcacd1b 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La app o tu organización no permiten las capturas de pantalla"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar captura de pantalla"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Compartir captura"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar más"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Descartar captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa de la captura de pantalla"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Escaneando rostro"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ocurrió un problema al obtener las tarjetas; vuelve a intentarlo más tarde"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuración de pantalla de bloqueo"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avión"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"No oirás la próxima alarma a la(s) <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
index f2f0601..f7037b0 100644
--- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Micrófono activado"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accedió al micrófono"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN está conectada."</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN está desconectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
index 4f738c5..cc167d5 100644
--- a/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Desactivado"</item>
     <item msgid="6866424167599381915">"Activado"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"No disponible"</item>
     <item msgid="2710157085538036590">"Desactivado"</item>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 8152879..88235fd 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"La aplicación o tu organización no permiten realizar capturas de pantalla"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar captura de pantalla"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Compartir captura de pantalla"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar más"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Cerrar captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa de captura de pantalla"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Cartera"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Escaneando cara"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Se ha producido un problema al obtener tus tarjetas. Inténtalo de nuevo más tarde."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ajustes de pantalla de bloqueo"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabajo"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"No oirás la próxima alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml
index cc78cf2..c4d8a69 100644
--- a/packages/SystemUI/res/values-es/strings_tv.xml
+++ b/packages/SystemUI/res/values-es/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Micrófono activado"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ha accedido a tu micrófono"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"La VPN está conectada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"La VPN está desconectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-es/tiles_states_strings.xml b/packages/SystemUI/res/values-es/tiles_states_strings.xml
index 1c2f211..1d1cd71 100644
--- a/packages/SystemUI/res/values-es/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-es/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Desactivado"</item>
     <item msgid="6866424167599381915">"Activado"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"No disponible"</item>
     <item msgid="2710157085538036590">"Desactivado"</item>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index e798f9f..c1b463f 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Rakendus või teie organisatsioon ei luba ekraanipilte jäädvustada"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Muutmine"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Ekraanipildi muutmine"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Jaga ekraanipilti"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Jäädvustage rohkem"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ekraanipildist loobumine"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekraanipildi eelvaade"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Häälabi"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Rahakott"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Luku avamine"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Seade on lukustatud"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Näo skannimine"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Avage kasutamiseks"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Teie kaartide hankimisel ilmnes probleem, proovige hiljem uuesti"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lukustuskuva seaded"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Tööprofiil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lennukirežiim"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Te ei kuule järgmist äratust kell <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-et/strings_tv.xml b/packages/SystemUI/res/values-et/strings_tv.xml
index 6f020c6..2857f2f 100644
--- a/packages/SystemUI/res/values-et/strings_tv.xml
+++ b/packages/SystemUI/res/values-et/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon on aktiivne"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s pääses teie mikrofonile juurde"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN on ühendatud"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-i ühendus on katkestatud"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Teenuse <xliff:g id="VPN_APP">%1$s</xliff:g> kaudu"</string>
diff --git a/packages/SystemUI/res/values-et/tiles_states_strings.xml b/packages/SystemUI/res/values-et/tiles_states_strings.xml
index bba2d82..044954d 100644
--- a/packages/SystemUI/res/values-et/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-et/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Väljas"</item>
     <item msgid="6866424167599381915">"Sees"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Pole saadaval"</item>
     <item msgid="2710157085538036590">"Väljas"</item>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 96378d7..a9a325a 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonoa"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ahots-laguntza"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Zorroa"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Desblokeatu"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Gailua blokeatuta dago"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Aurpegia eskaneatzen"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desblokeatu erabiltzeko"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Arazo bat izan da txartelak eskuratzean. Saiatu berriro geroago."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Pantaila blokeatuaren ezarpenak"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Work profila"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Hegaldi modua"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Ez duzu entzungo hurrengo alarma (<xliff:g id="WHEN">%1$s</xliff:g>)"</string>
diff --git a/packages/SystemUI/res/values-eu/strings_tv.xml b/packages/SystemUI/res/values-eu/strings_tv.xml
index c9c30c7..a52f370 100644
--- a/packages/SystemUI/res/values-eu/strings_tv.xml
+++ b/packages/SystemUI/res/values-eu/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofonoa aktibatuta dago"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s aplikazioak mikrofonoa atzitu du"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN sarera konektatuta dago"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ez dago sarera konektatuta"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> bidez"</string>
diff --git a/packages/SystemUI/res/values-eu/tiles_states_strings.xml b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
index 2fcddd4..bb6c384 100644
--- a/packages/SystemUI/res/values-eu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-eu/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Desaktibatuta"</item>
     <item msgid="6866424167599381915">"Aktibatuta"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Ez dago erabilgarri"</item>
     <item msgid="2710157085538036590">"Desaktibatuta"</item>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index e79eba0..9260abd 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"برنامه یا سازمان شما اجازه نمی‌دهند نماگرفت بگیرید."</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"ویرایش"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"ویرایش نماگرفت"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"هم‌رسانی نماگرفت"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"ضبط محتوای بیشتر"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"رد کردن نماگرفت"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"پیش‌نمایش نماگرفت"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"تلفن"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"دستیار صوتی"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"باز کردن قفل"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"دستگاه قفل است"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"درحال اسکن کردن چهره"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"برای استفاده، قفل را باز کنید"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"هنگام دریافت کارت‌ها مشکلی پیش آمد، لطفاً بعداً دوباره امتحان کنید"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"تنظیمات صفحه قفل"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"نمایه کاری"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"حالت هواپیما"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"در ساعت <xliff:g id="WHEN">%1$s</xliff:g>، دیگر صدای زنگ ساعت را نمی‌شنوید"</string>
diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml
index 3ba9b4e..27711e6 100644
--- a/packages/SystemUI/res/values-fa/strings_tv.xml
+++ b/packages/SystemUI/res/values-fa/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"میکروفون فعال است"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"‏%1$s به میکروفون شما دسترسی پیدا کرد"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"‏VPN متصل است"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"‏VPN قطع است"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ازطریق <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-fa/tiles_states_strings.xml b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
index d3662f9..13c7f41 100644
--- a/packages/SystemUI/res/values-fa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fa/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"خاموش"</item>
     <item msgid="6866424167599381915">"روشن"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"دردسترس نیست"</item>
     <item msgid="2710157085538036590">"خاموش"</item>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4009669..5c36c7c 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Puhelin"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ääniapuri"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Avaa lukitus"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Laite lukittu"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Kasvojen skannaus"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Avaa lukitus ja käytä"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Korttien noutamisessa oli ongelma, yritä myöhemmin uudelleen"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lukitusnäytön asetukset"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Työprofiili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lentokonetila"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Et kuule seuraavaa hälytystäsi (<xliff:g id="WHEN">%1$s</xliff:g>)."</string>
diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml
index 6312837..fa178b0 100644
--- a/packages/SystemUI/res/values-fi/strings_tv.xml
+++ b/packages/SystemUI/res/values-fi/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofoni aktiivinen"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s sai pääsyn mikrofoniisi"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN on yhdistetty"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ei ole yhdistettynä"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Palvelun <xliff:g id="VPN_APP">%1$s</xliff:g> kautta"</string>
diff --git a/packages/SystemUI/res/values-fi/tiles_states_strings.xml b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
index 5a88f19..47013d1 100644
--- a/packages/SystemUI/res/values-fi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fi/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Poissa päältä"</item>
     <item msgid="6866424167599381915">"Päällä"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Ei saatavilla"</item>
     <item msgid="2710157085538036590">"Poissa päältä"</item>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 1d19d0e..c5d8a48 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'application ou votre organisation n\'autorise pas les saisies d\'écran"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Modifier"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Modifier la capture d\'écran"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Partagez la capture d\'écran"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturer plus"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Fermer la capture d\'écran"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Aperçu de la capture d\'écran"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Téléphone"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistance vocale"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portefeuille"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Déverrouiller"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Appareil verrouillé"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Numérisation du visage"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Un problème est survenu lors de la récupération de vos cartes, veuillez réessayer plus tard"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Vous n\'entendrez pas votre prochaine alarme à <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
index 0925abe..9812b9f 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Microphone actif"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s a accédé à votre microphone"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"RPV connecté"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"RPV déconnecté"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Par <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
index 30870dd..fb929fc 100644
--- a/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Désactivé"</item>
     <item msgid="6866424167599381915">"Activé"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Non disponible"</item>
     <item msgid="2710157085538036590">"Désactivée"</item>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index b571e0c..ead26a3 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Les captures d\'écran ne sont pas autorisées par l\'application ni par votre organisation"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Modifier"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Modifier la capture d\'écran"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Partager la capture d\'écran"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturer plus"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Fermer la capture d\'écran"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Aperçu de la capture d\'écran"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Téléphoner"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistance vocale"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portefeuille"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Déverrouiller"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Appareil verrouillé"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Analyse du visage en cours"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Déverrouiller pour utiliser"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Problème de récupération de vos cartes. Réessayez plus tard"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Paramètres de l\'écran de verrouillage"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil professionnel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode Avion"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Vous n\'entendrez pas votre prochaine alarme <xliff:g id="WHEN">%1$s</xliff:g>."</string>
diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml
index 3a33aad..0a776db 100644
--- a/packages/SystemUI/res/values-fr/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Micro actif"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s a accédé à votre micro"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN connecté"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN déconnecté"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-fr/tiles_states_strings.xml b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
index 5898e0c..971477d 100644
--- a/packages/SystemUI/res/values-fr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-fr/tiles_states_strings.xml
@@ -63,7 +63,7 @@
   </string-array>
   <string-array name="tile_states_rotation">
     <item msgid="4578491772376121579">"Indisponible"</item>
-    <item msgid="5776427577477729185">"Désactivé"</item>
+    <item msgid="5776427577477729185">"Désactivée"</item>
     <item msgid="7105052717007227415">"Activée"</item>
   </string-array>
   <string-array name="tile_states_bt">
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Désactivé"</item>
     <item msgid="6866424167599381915">"Activé"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Indisponible"</item>
     <item msgid="2710157085538036590">"Désactivée"</item>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index ef91651..3aa3e3f 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A aplicación ou a túa organización non permite realizar capturas de pantalla"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar a captura de pantalla"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Compartir captura de pantalla"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar máis"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignorar a captura de pantalla"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Vista previa da captura de pantalla"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Teléfono"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistente de voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Analizando cara"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Produciuse un problema ao obter as tarxetas. Téntao de novo máis tarde"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configuración da pantalla de bloqueo"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de traballo"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avión"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Non escoitarás a alarma seguinte <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-gl/strings_tv.xml b/packages/SystemUI/res/values-gl/strings_tv.xml
index 679c21d..feb739a 100644
--- a/packages/SystemUI/res/values-gl/strings_tv.xml
+++ b/packages/SystemUI/res/values-gl/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Micrófono activo"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s accedeu ao teu micrófono"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"A través de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-gl/tiles_states_strings.xml b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
index c627ec0..e362238 100644
--- a/packages/SystemUI/res/values-gl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gl/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Non"</item>
     <item msgid="6866424167599381915">"Si"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Non dispoñible"</item>
     <item msgid="2710157085538036590">"Non"</item>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 1483cc9..be707d8 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ઍપ્લિકેશન કે તમારી સંસ્થા દ્વારા સ્ક્રીનશૉટ લેવાની મંજૂરી નથી"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"ફેરફાર કરો"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"સ્ક્રીનશૉટમાં ફેરફાર કરો"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"સ્ક્રીનશૉટ શેર કરો"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"વધુ કૅપ્ચર કરો"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"સ્ક્રીનશૉટ છોડી દો"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"સ્ક્રીનશૉટનો પ્રીવ્યૂ"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ફોન"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"વૉઇસ સહાય"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"વૉલેટ"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"અનલૉક કરો"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ડિવાઇસ લૉક કરેલું છે"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ચહેરો સ્કૅન કરવો"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ઉપયોગ કરવા માટે અનલૉક કરો"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"તમારા કાર્ડની માહિતી મેળવવામાં સમસ્યા આવી હતી, કૃપા કરીને થોડા સમય પછી ફરી પ્રયાસ કરો"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"લૉક સ્ક્રીનના સેટિંગ"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ઑફિસની પ્રોફાઇલ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"એરપ્લેન મોડ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"તમે <xliff:g id="WHEN">%1$s</xliff:g> એ તમારો આગલો એલાર્મ સાંભળશો નહીં"</string>
diff --git a/packages/SystemUI/res/values-gu/strings_tv.xml b/packages/SystemUI/res/values-gu/strings_tv.xml
index e226503..97f9bcc 100644
--- a/packages/SystemUI/res/values-gu/strings_tv.xml
+++ b/packages/SystemUI/res/values-gu/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"માઇક્રોફોન સક્રિય છે"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$sએ તમારો માઇક્રોફોન ઍક્સેસ કર્યો હતો"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN કનેક્ટ કરેલું છે"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ડિસ્કનેક્ટ કરેલું છે"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> મારફતે"</string>
diff --git a/packages/SystemUI/res/values-gu/tiles_states_strings.xml b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
index 67dfb34..12c2de7 100644
--- a/packages/SystemUI/res/values-gu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-gu/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"બંધ છે"</item>
     <item msgid="6866424167599381915">"ચાલુ છે"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"ઉપલબ્ધ નથી"</item>
     <item msgid="2710157085538036590">"બંધ છે"</item>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 08417e4..80b52d2 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"फ़ोन"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज़ से डिवाइस का इस्तेमाल"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"वॉलेट बटन"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"अनलॉक करें"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"डिवाइस लॉक है"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"डिवाइस अनलॉक करने के लिए चेहरा स्कैन किया जाता है"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"इस्तेमाल करने के लिए, डिवाइस अनलॉक करें"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"आपके कार्ड की जानकारी पाने में कोई समस्या हुई है. कृपया बाद में कोशिश करें"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लॉक स्क्रीन की सेटिंग"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"वर्क प्रोफ़ाइल"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"हवाई जहाज़ मोड"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"आपको <xliff:g id="WHEN">%1$s</xliff:g> पर अपना अगला अलार्म नहीं सुनाई देगा"</string>
diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml
index cc9a562..2018c36 100644
--- a/packages/SystemUI/res/values-hi/strings_tv.xml
+++ b/packages/SystemUI/res/values-hi/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"माइक्रोफ़ोन चालू है"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ने आपका माइक्रोफ़ोन ऐक्सेस किया था"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"वीपीएन कनेक्ट हो गया है"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"वीपीएन डिसकनेक्ट हो गया है"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> के ज़रिए"</string>
diff --git a/packages/SystemUI/res/values-hi/tiles_states_strings.xml b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
index 40d15e7..f7fce26 100644
--- a/packages/SystemUI/res/values-hi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hi/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"बंद है"</item>
     <item msgid="6866424167599381915">"चालू है"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"उपलब्ध नहीं है"</item>
     <item msgid="2710157085538036590">"बंद है"</item>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 59aa397..8864901 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Aplikacija ili vaša organizacija ne dopuštaju snimanje zaslona"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Uredi"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Uređivanje snimke zaslona"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Podijeli snimku zaslona"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Snimi više"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Odbacivanje snimke zaslona"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pregled snimke zaslona"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovna pomoć"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Otključavanje"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Uređaj je zaključan"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skeniranje lica"</string>
@@ -468,6 +469,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Otključajte da biste koristili"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Pojavio se problem prilikom dohvaćanja kartica, pokušajte ponovo kasnije"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Postavke zaključanog zaslona"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Poslovni profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Način rada u zrakoplovu"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nećete čuti sljedeći alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml
index 633847c..d87f46f 100644
--- a/packages/SystemUI/res/values-hr/strings_tv.xml
+++ b/packages/SystemUI/res/values-hr/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon aktivan"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacija %1$s pristupila je mikrofonu"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN je spojen"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN je isključen"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Putem mreže <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-hr/tiles_states_strings.xml b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
index 5622a82..90b8cce 100644
--- a/packages/SystemUI/res/values-hr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hr/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Isključeno"</item>
     <item msgid="6866424167599381915">"Uključeno"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Nedostupno"</item>
     <item msgid="2710157085538036590">"Isključeno"</item>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index fbcaa99..d8f2238 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Az alkalmazás vagy az Ön szervezete nem engedélyezi képernyőkép készítését"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Szerkesztés"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Képernyőkép szerkesztése"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Képernyőkép megosztása"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Több rögzítése"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Képernyőkép elvetése"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Képernyőkép előnézete"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hangsegéd"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Feloldás"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Az eszköz zárolva van"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Arc keresése"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Oldja fel a használathoz"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Probléma merült fel a kártyák lekérésekor, próbálja újra később"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Lezárási képernyő beállításai"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Munkahelyi profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Repülős üzemmód"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nem fogja hallani az ébresztést ekkor: <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml
index 97c375a..0c7313d 100644
--- a/packages/SystemUI/res/values-hu/strings_tv.xml
+++ b/packages/SystemUI/res/values-hu/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"A mikrofon aktív"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"A(z) %1$s hozzáfért a mikrofonhoz"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN-kapcsolat létrejött"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN-kapcsolat megszakadt"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Ezzel: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-hu/tiles_states_strings.xml b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
index 113e61f..6e1d636 100644
--- a/packages/SystemUI/res/values-hu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hu/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Ki"</item>
     <item msgid="6866424167599381915">"Be"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Nem áll rendelkezésre"</item>
     <item msgid="2710157085538036590">"Ki"</item>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index b70be8a..c5f5595 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Հեռախոս"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ձայնային հուշումներ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Դրամապանակ"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Ապակողպել"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Սարքը կողպված է"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Դեմքի սկանավորում"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ապակողպել՝ օգտագործելու համար"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Չհաջողվեց բեռնել քարտերը։ Նորից փորձեք։"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Կողպէկրանի կարգավորումներ"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Android for Work-ի պրոֆիլ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Ավիառեժիմ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Ժամը <xliff:g id="WHEN">%1$s</xliff:g>-ի զարթուցիչը չի զանգի"</string>
diff --git a/packages/SystemUI/res/values-hy/strings_tv.xml b/packages/SystemUI/res/values-hy/strings_tv.xml
index 3f46b90..f01e10c 100644
--- a/packages/SystemUI/res/values-hy/strings_tv.xml
+++ b/packages/SystemUI/res/values-hy/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Խոսափողն ակտիվացված է"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s հավելվածն օգտագործել է ձեր խոսափողը"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-ը միացված է"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-ն անջատված է"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ի միջոցով"</string>
diff --git a/packages/SystemUI/res/values-hy/tiles_states_strings.xml b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
index a8d89d22..3e9c28c 100644
--- a/packages/SystemUI/res/values-hy/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-hy/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Անջատված է"</item>
     <item msgid="6866424167599381915">"Միացված է"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Հասանելի չէ"</item>
     <item msgid="2710157085538036590">"Անջատված է"</item>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 3333a28..1bae18e 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -108,6 +108,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telepon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Bantuan Suara"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Buka kunci"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Perangkat terkunci"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Memindai wajah"</string>
@@ -465,6 +467,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Buka kunci untuk menggunakan"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Terjadi masalah saat mendapatkan kartu Anda, coba lagi nanti"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setelan layar kunci"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mode pesawat"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar alarm berikutnya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
index 110eb09..8d177e6 100644
--- a/packages/SystemUI/res/values-in/strings_tv.xml
+++ b/packages/SystemUI/res/values-in/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon Aktif"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s mengakses mikrofon"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN terhubung"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN terputus"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-in/tiles_states_strings.xml b/packages/SystemUI/res/values-in/tiles_states_strings.xml
index 84a9342..70ee1bc 100644
--- a/packages/SystemUI/res/values-in/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-in/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Nonaktif"</item>
     <item msgid="6866424167599381915">"Aktif"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Tidak tersedia"</item>
     <item msgid="2710157085538036590">"Nonaktif"</item>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 060cb77..9c3889d 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Forritið eða fyrirtækið þitt leyfir ekki skjámyndatöku"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Breyta"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Breyta skjámynd"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Deila skjámynd"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Mynda meira"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Loka skjámynd"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Forskoðun skjámyndar"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Sími"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Raddaðstoð"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Veski"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Taka úr lás"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Tækið er læst"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Andlit skannað"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Taktu úr lás til að nota"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Vandamál kom upp við að sækja kortin þín. Reyndu aftur síðar"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Stillingar fyrir læstan skjá"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Vinnusnið"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flugstilling"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Ekki mun heyrast í vekjaranum <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-is/strings_tv.xml b/packages/SystemUI/res/values-is/strings_tv.xml
index eb0f450..a929a45 100644
--- a/packages/SystemUI/res/values-is/strings_tv.xml
+++ b/packages/SystemUI/res/values-is/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Hljóðnemi virkur"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s fékk aðgang að hljóðnemanum þínum"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tengt"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er ekki tengt"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Í gegnum <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-is/tiles_states_strings.xml b/packages/SystemUI/res/values-is/tiles_states_strings.xml
index 5616d74..3565a9c 100644
--- a/packages/SystemUI/res/values-is/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-is/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Slökkt"</item>
     <item msgid="6866424167599381915">"Kveikt"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Ekki í boði"</item>
     <item msgid="2710157085538036590">"Slökkt"</item>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index f99b6ba..4a5530f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"L\'acquisizione di screenshot non è consentita dall\'app o dall\'organizzazione"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Modifica"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Modifica screenshot"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Condividi screenshot"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Acquisisci di più"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignora screenshot"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Anteprima screenshot"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefono"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portafoglio"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Sblocca"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloccato"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scansione del viso"</string>
@@ -212,8 +213,8 @@
     <string name="accessibility_clear_all" msgid="970525598287244592">"Cancella tutte le notifiche."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
+      <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
       <item quantity="other">Altre <xliff:g id="NUMBER_1">%s</xliff:g> notifiche nel gruppo.</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> altra notifica nel gruppo.</item>
     </plurals>
     <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"Lo schermo è bloccato in orientamento orizzontale."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"Lo schermo è bloccato in orientamento verticale."</string>
@@ -262,8 +263,8 @@
     <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Attivazione…"</string>
     <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Risp. dati attivo"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
+      <item quantity="one">%d devices</item>
       <item quantity="other">%d dispositivi</item>
-      <item quantity="one">%d dispositivo</item>
     </plurals>
     <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Torcia"</string>
     <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Fotocamera in uso"</string>
@@ -342,8 +343,8 @@
     <string name="user_add_user_message_short" msgid="2599370307878014791">"Il nuovo utente, una volta aggiunto, deve impostare il proprio spazio.\n\nQualsiasi utente può aggiornare le app per tutti gli altri."</string>
     <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite di utenti raggiunto"</string>
     <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398">
+      <item quantity="one">You can add up to <xliff:g id="COUNT">%d</xliff:g> users.</item>
       <item quantity="other">Puoi aggiungere fino a <xliff:g id="COUNT">%d</xliff:g> utenti.</item>
-      <item quantity="one">È possibile creare un solo utente.</item>
     </plurals>
     <string name="user_remove_user_title" msgid="9124124694835811874">"Rimuovere l\'utente?"</string>
     <string name="user_remove_user_message" msgid="6702834122128031833">"Tutte le app e i dati di questo utente verranno eliminati."</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Sblocca per usare"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Si è verificato un problema durante il recupero delle tue carte. Riprova più tardi."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Impostazioni schermata di blocco"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profilo di lavoro"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modalità aereo"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Non sentirai la tua prossima sveglia <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -529,12 +534,12 @@
     <string name="snooze_undo" msgid="2738844148845992103">"Annulla"</string>
     <string name="snoozed_for_time" msgid="7586689374860469469">"Posticipato di <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <plurals name="snoozeHourOptions" formatted="false" msgid="2066838694120718170">
+      <item quantity="one">%d hours</item>
       <item quantity="other">%d ore</item>
-      <item quantity="one">%d ora</item>
     </plurals>
     <plurals name="snoozeMinuteOptions" formatted="false" msgid="8998483159208055980">
+      <item quantity="one">%d minutes</item>
       <item quantity="other">%d minuti</item>
-      <item quantity="one">%d minuto</item>
     </plurals>
     <string name="battery_detail_switch_title" msgid="6940976502957380405">"Risparmio energetico"</string>
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Pulsante <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -756,8 +761,8 @@
     <string name="quick_controls_title" msgid="6839108006171302273">"Controllo dispositivi"</string>
     <string name="controls_providers_title" msgid="6879775889857085056">"Scegli un\'app per aggiungere controlli"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
+      <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> controlli aggiunti.</item>
       <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlli aggiunti.</item>
-      <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> controllo aggiunto.</item>
     </plurals>
     <string name="controls_removed" msgid="3731789252222856959">"Rimosso"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Aggiunto ai preferiti"</string>
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
index 45d3369..38ca86d 100644
--- a/packages/SystemUI/res/values-it/strings_tv.xml
+++ b/packages/SystemUI/res/values-it/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Microfono attivo"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ha avuto accesso al tuo microfono"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN connessa"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN disconnessa"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Tramite <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-it/tiles_states_strings.xml b/packages/SystemUI/res/values-it/tiles_states_strings.xml
index f18536c..a9c67d5 100644
--- a/packages/SystemUI/res/values-it/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-it/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Off"</item>
     <item msgid="6866424167599381915">"On"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Non disponibile"</item>
     <item msgid="2710157085538036590">"Off"</item>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 98fcf42..9368808 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"האפליקציה או הארגון שלך אינם מתירים ליצור צילומי מסך"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"עריכה"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"עריכת צילום מסך"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"שיתוף של צילום מסך"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"צילום תוכן נוסף"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"סגירת צילום מסך"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"תצוגה מקדימה של צילום מסך"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"טלפון"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"האסיסטנט"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ארנק"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"ביטול נעילה"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"המכשיר נעול"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"סורק פנים"</string>
@@ -471,6 +472,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"יש לבטל את הנעילה כדי להשתמש"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"הייתה בעיה בקבלת הכרטיסים שלך. כדאי לנסות שוב מאוחר יותר"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"הגדרות מסך הנעילה"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"פרופיל עבודה"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"מצב טיסה"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"לא ניתן יהיה לשמוע את ההתראה הבאה שלך <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml
index 5c091d3..925b523 100644
--- a/packages/SystemUI/res/values-iw/strings_tv.xml
+++ b/packages/SystemUI/res/values-iw/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"המיקרופון פעיל"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"‏לאפליקציה %1$s יש גישה למיקרופון שלך"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"‏ה-VPN מחובר"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"‏ה-VPN מנותק"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"דרך <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-iw/tiles_states_strings.xml b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
index 0be95b8..c769a84 100644
--- a/packages/SystemUI/res/values-iw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-iw/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"כבוי"</item>
     <item msgid="6866424167599381915">"פועל"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"לא זמין"</item>
     <item msgid="2710157085538036590">"כבוי"</item>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 3eb2b65..bb35ad8 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"音声アシスト"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ウォレット"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"ロック解除"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"デバイスはロックされています"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"顔のスキャン"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ロックを解除して使用"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"カードの取得中に問題が発生しました。しばらくしてからもう一度お試しください"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ロック画面の設定"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"仕事用プロファイル"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"機内モード"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"次回のアラーム(<xliff:g id="WHEN">%1$s</xliff:g>)は鳴りません"</string>
diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
index c37958f..6a94295 100644
--- a/packages/SystemUI/res/values-ja/strings_tv.xml
+++ b/packages/SystemUI/res/values-ja/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"マイク: 有効"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s がマイクにアクセスしました"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN に接続しました"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN に接続していません"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> 経由"</string>
diff --git a/packages/SystemUI/res/values-ja/tiles_states_strings.xml b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
index bee2deb..6383acc 100644
--- a/packages/SystemUI/res/values-ja/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ja/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"OFF"</item>
     <item msgid="6866424167599381915">"ON"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"使用不可"</item>
     <item msgid="2710157085538036590">"OFF"</item>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index d788fdb..94eb7c2 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ეკრანის ანაბეჭდების შექმნა არ არის ნებადართული აპის ან თქვენი ორგანიზაციის მიერ"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"რედაქტირება"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"ეკრანის ანაბეჭდის რედაქტირება"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"ეკრანის ანაბეჭდის გაზიარება"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"მეტის აღბეჭდვა"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ეკრანის ანაბეჭდის დახურვა"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ეკრანის ანაბეჭდის გადახედვა"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ტელეფონი"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ხმოვანი დახმარება"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"განბლოკვა"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"მოწყობილობა ჩაკეტილია"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"მიმდინარეობს სახის სკანირება"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"გამოსაყენებლად განბლოკვა"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"თქვენი ბარათების მიღებისას პრობლემა წარმოიშვა. ცადეთ ხელახლა მოგვიანებით"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ჩაკეტილი ეკრანის პარამეტრები"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"სამსახურის პროფილი"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"თვითმფრინავის რეჟიმი"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"ვერ გაიგონებთ მომდევნო მაღვიძარას <xliff:g id="WHEN">%1$s</xliff:g>-ზე"</string>
diff --git a/packages/SystemUI/res/values-ka/strings_tv.xml b/packages/SystemUI/res/values-ka/strings_tv.xml
index 8db4b1b..3cffcee 100644
--- a/packages/SystemUI/res/values-ka/strings_tv.xml
+++ b/packages/SystemUI/res/values-ka/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"მიკროფონი აქტიურია"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s-მა გამოიყენა თქვენი მიკროფონი"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN დაკავშირებულია"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN გათიშულია"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ის მიერ"</string>
diff --git a/packages/SystemUI/res/values-ka/tiles_states_strings.xml b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
index eb5f4704..4c23237 100644
--- a/packages/SystemUI/res/values-ka/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ka/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"გამორთულია"</item>
     <item msgid="6866424167599381915">"ჩართულია"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"მიუწვდომელია"</item>
     <item msgid="2710157085538036590">"გამორთულია"</item>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index ad345a9..18ce927 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Қолданба немесе ұйым скриншоттар түсіруге рұқсат етпейді"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Өзгерту"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Скриншотты өзгерту"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Скриншотты бөлісу"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Тағы суретке түсіру"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Скриншотты жабу"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотты алдын ала қарау"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Дауыс көмекшісі"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Әмиян"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Бекітпесін ашу"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Құрылғы құлыпталды."</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Бетті сканерлеу"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Пайдалану үшін құлыпты ашу"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Карталарыңыз алынбады, кейінірек қайталап көріңіз."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Экран құлпының параметрлері"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Жұмыс профилі"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Ұшақ режимі"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Келесі <xliff:g id="WHEN">%1$s</xliff:g> дабылыңызды есітпейсіз"</string>
diff --git a/packages/SystemUI/res/values-kk/strings_tv.xml b/packages/SystemUI/res/values-kk/strings_tv.xml
index a56b4aa..60683d3 100644
--- a/packages/SystemUI/res/values-kk/strings_tv.xml
+++ b/packages/SystemUI/res/values-kk/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Микрофон қосулы"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s микрофоныңызды пайдаланды."</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN қосылған"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ажыратылған"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> арқылы жалғанған"</string>
diff --git a/packages/SystemUI/res/values-kk/tiles_states_strings.xml b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
index cdb5530..7a4676f 100644
--- a/packages/SystemUI/res/values-kk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kk/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Өшірулі"</item>
     <item msgid="6866424167599381915">"Қосулы"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Қолжетімсіз"</item>
     <item msgid="2710157085538036590">"Өшірулі"</item>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 7f35811..b86f9b5 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ការថត​រូបអេក្រង់​មិនត្រូវ​បាន​អនុញ្ញាត​ដោយ​កម្មវិធី​នេះ ឬ​ស្ថាប័ន​របស់អ្នក"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"កែ"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"កែ​រូបថត​អេក្រង់"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"ចែករំលែករូបថតអេក្រង់"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"ថត​ច្រើនទៀត"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ច្រានចោល​រូបថត​អេក្រង់"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ការមើល​រូបថត​អេក្រង់​សាកល្បង"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ទូរសព្ទ"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ជំនួយសំឡេង"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"កាបូប"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"ដោះ​​សោ"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"បានចាក់សោ​ឧបករណ៍"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ការ​ស្កេន​មុខ"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ដោះសោដើម្បីប្រើប្រាស់"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"មានបញ្ហា​ក្នុងការទាញយក​កាត​របស់អ្នក សូម​ព្យាយាមម្ដងទៀត​នៅពេលក្រោយ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ការកំណត់អេក្រង់ចាក់សោ"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ប្រវត្តិរូបការងារ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ពេលជិះយន្តហោះ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"អ្នកនឹងមិនលឺម៉ោងរោទ៍ <xliff:g id="WHEN">%1$s</xliff:g> បន្ទាប់របស់អ្នកទេ"</string>
diff --git a/packages/SystemUI/res/values-km/strings_tv.xml b/packages/SystemUI/res/values-km/strings_tv.xml
index c654e6d..b6c7fd5 100644
--- a/packages/SystemUI/res/values-km/strings_tv.xml
+++ b/packages/SystemUI/res/values-km/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"មីក្រូហ្វូន​កំពុង​ដំណើរការ"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s បានចូលប្រើ​មីក្រូហ្វូន​របស់អ្នក"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ត្រូវបានភ្ជាប់"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ត្រូវបានផ្ដាច់"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"តាម​រយៈ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-km/tiles_states_strings.xml b/packages/SystemUI/res/values-km/tiles_states_strings.xml
index 4ac3c83..be3f754 100644
--- a/packages/SystemUI/res/values-km/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-km/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"បិទ"</item>
     <item msgid="6866424167599381915">"បើក"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"មិនមានទេ"</item>
     <item msgid="2710157085538036590">"បិទ"</item>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 1d818ce..614b0ca 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ಅಪ್ಲಿಕೇಶನ್ ಅಥವಾ ಸಂಸ್ಥೆಯು ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ಗಳನ್ನು ತೆಗೆಯುವುದನ್ನು ಅನುಮತಿಸುವುದಿಲ್ಲ"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"ಎಡಿಟ್ ಮಾಡಿ"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್‌ ಅನ್ನು ಎಡಿಟ್ ಮಾಡಿ"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"ಇನ್ನಷ್ಟು ಕ್ಯಾಪ್ಚರ್ ಮಾಡಿ"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ಸ್ಕ್ರೀನ್‌ಶಾಟ್ ಅನ್ನು ವಜಾಗೊಳಿಸಿ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ಸ್ಕ್ರೀನ್‍ಶಾಟ್‍ನ ಪೂರ್ವವೀಕ್ಷಣೆ"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ಫೋನ್"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ಧ್ವನಿ ಸಹಾಯಕ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"ಅನ್‌ಲಾಕ್"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ಸಾಧನ ಲಾಕ್ ಆಗಿದೆ"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ಮುಖವನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ಬಳಸಲು ಅನ್‌ಲಾಕ್ ಮಾಡಿ"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"ನಿಮ್ಮ ಕಾರ್ಡ್‌ಗಳನ್ನು ಪಡೆಯುವಾಗ ಸಮಸ್ಯೆ ಉಂಟಾಗಿದೆ, ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ಲಾಕ್ ಸ್ಕ್ರ್ರೀನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"ನಿಮ್ಮ ಮುಂದಿನ <xliff:g id="WHEN">%1$s</xliff:g> ಅಲಾರಮ್ ಅನ್ನು ನೀವು ಆಲಿಸುವುದಿಲ್ಲ"</string>
diff --git a/packages/SystemUI/res/values-kn/strings_tv.xml b/packages/SystemUI/res/values-kn/strings_tv.xml
index 3955a09..2a9a604 100644
--- a/packages/SystemUI/res/values-kn/strings_tv.xml
+++ b/packages/SystemUI/res/values-kn/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"ಮೈಕ್ರೋಫೋನ್‌ ಸಕ್ರಿಯವಾಗಿದೆ"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ನಿಮ್ಮ ಮೈಕ್ರೋಫೋನ್ ಅನ್ನು ಪ್ರವೇಶಿಸಿದೆ"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ಕನೆಕ್ಷನ್ ಕಡಿತಗೊಂಡಿದೆ"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ಮೂಲಕ"</string>
diff --git a/packages/SystemUI/res/values-kn/tiles_states_strings.xml b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
index ae8f5a2..7eea89d 100644
--- a/packages/SystemUI/res/values-kn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-kn/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"ಆಫ್ ಮಾಡಿ"</item>
     <item msgid="6866424167599381915">"ಆನ್ ಮಾಡಿ"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"ಲಭ್ಯವಿಲ್ಲ"</item>
     <item msgid="2710157085538036590">"ಆಫ್ ಮಾಡಿ"</item>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 0e01272..fff2b55 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"전화"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"음성 지원"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"지갑"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"잠금 해제"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"기기 잠김"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"얼굴 스캔 중"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"잠금 해제하여 사용"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"카드를 가져오는 중에 문제가 발생했습니다. 나중에 다시 시도해 보세요."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"잠금 화면 설정"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"직장 프로필"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"비행기 모드"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>에 다음 알람을 들을 수 없습니다."</string>
diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml
index b9fb537..af020fd 100644
--- a/packages/SystemUI/res/values-ko/strings_tv.xml
+++ b/packages/SystemUI/res/values-ko/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"마이크 사용 중"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s에서 내 마이크에 액세스했습니다."</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN에 연결됨"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 연결이 해제됨"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>에 연결됨"</string>
diff --git a/packages/SystemUI/res/values-ko/tiles_states_strings.xml b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
index b583f24..fd03b4d 100644
--- a/packages/SystemUI/res/values-ko/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ko/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"꺼짐"</item>
     <item msgid="6866424167599381915">"켜짐"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"이용 불가"</item>
     <item msgid="2710157085538036590">"꺼짐"</item>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 2456ad4..81e3d5d 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Скриншот тартууга колдонмо же ишканаңыз тыюу салган."</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Түзөтүү"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Скриншотту түзөтүү"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Скриншотту бөлүшүү"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Көбүрөөк тартуу"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Скриншотту четке кагуу"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Скриншотту алдын ала көрүү"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Үн жардамчысы"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Капчык"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Кулпусун ачуу"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Түзмөк кулпуланды"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Жүз скандалууда"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Колдонуу үчүн кулпусун ачыңыз"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Кыйытмаларды алууда ката кетти. Бир аздан кийин кайталап көрүңүз."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Кулпуланган экран жөндөөлөрү"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Жумуш профили"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Учак режими"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> боло турган кийинки эскертмени укпайсыз"</string>
diff --git a/packages/SystemUI/res/values-ky/strings_tv.xml b/packages/SystemUI/res/values-ky/strings_tv.xml
index 52b2375..b37f1be 100644
--- a/packages/SystemUI/res/values-ky/strings_tv.xml
+++ b/packages/SystemUI/res/values-ky/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Микрофон күйүк"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s микрофонуңузду колдонууда"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN туташтырылды"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ажыратылды"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> аркылуу"</string>
diff --git a/packages/SystemUI/res/values-ky/tiles_states_strings.xml b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
index 6e75bf3..27aabb8 100644
--- a/packages/SystemUI/res/values-ky/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ky/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Өчүк"</item>
     <item msgid="6866424167599381915">"Күйүк"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Жеткиликсиз"</item>
     <item msgid="2710157085538036590">"Өчүк"</item>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index edbda76..ed5db04 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ແອັບ ຫຼື ອົງກອນຂອງທ່ານບໍ່ອະນຸຍາດໃຫ້ຖ່າຍຮູບໜ້າຈໍ"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"ແກ້ໄຂ"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"ແກ້ໄຂຮູບໜ້າຈໍ"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"ແບ່ງປັນຮູບໜ້າຈໍ"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"ຖ່າຍຮູບເພີ່ມເຕີມ"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ປິດຮູບໜ້າຈໍ"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ຕົວຢ່າງຮູບໜ້າຈໍ"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ໂທລະສັບ"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ຊ່ວຍ​ເຫຼືອ​ທາງ​ສຽງ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ກະເປົາ"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"ປົດລັອກ"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ອຸປະກອນຖືກລັອກໄວ້"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ການສະແກນໜ້າ"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ປົດລັອກເພື່ອໃຊ້"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"ເກີດບັນຫາໃນການໂຫຼດບັດຂອງທ່ານ, ກະລຸນາລອງໃໝ່ໃນພາຍຫຼັງ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ການຕັ້ງຄ່າໜ້າຈໍລັອກ"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ໂໝດເຮືອ​ບິນ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"ທ່ານ​ຈະ​ບໍ່​ໄດ້​ຍິນ​ສຽງ​ໂມງ​ປ <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-lo/strings_tv.xml b/packages/SystemUI/res/values-lo/strings_tv.xml
index d2de125..3b53434 100644
--- a/packages/SystemUI/res/values-lo/strings_tv.xml
+++ b/packages/SystemUI/res/values-lo/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"ໄມໂຄຣໂຟນເປີດໃຊ້ຢູ່"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ເຂົ້າເຖິງໄມໂຄຣໂຟນຂອງທ່ານແລ້ວ"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"ເຊື່ອມຕໍ່ VPN ແລ້ວ"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ຕັດການເຊື່ອມຕໍ່ VPN ແລ້ວ"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ຜ່ານ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-lo/tiles_states_strings.xml b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
index ac5da6f..cbb4e9d 100644
--- a/packages/SystemUI/res/values-lo/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lo/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"ປິດ"</item>
     <item msgid="6866424167599381915">"ເປີດ"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"ບໍ່ສາມາດໃຊ້ໄດ້"</item>
     <item msgid="2710157085538036590">"ປິດ"</item>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 0f6d53e..b040dde 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Jūsų organizacijoje arba naudojant šią programą neleidžiama daryti ekrano kopijų"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Redaguoti"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Redaguoti ekrano kopiją"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Bendrinti ekrano kopiją"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Fiksuoti daugiau"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Praleisti ekrano kopiją"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekrano kopijos peržiūra"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonas"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Piniginė"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Atrakinti"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Įrenginys užrakintas"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Nuskaitomas veidas"</string>
@@ -471,6 +472,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Atrakinti, kad būtų galima naudoti"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Gaunant korteles kilo problema, bandykite dar kartą vėliau"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Užrakinimo ekrano nustatymai"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Darbo profilis"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lėktuvo režimas"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Negirdėsite kito signalo <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml
index df23a61..79a0e8f 100644
--- a/packages/SystemUI/res/values-lt/strings_tv.xml
+++ b/packages/SystemUI/res/values-lt/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofonas aktyvus"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"„%1$s“ pasiekė jūsų mikrofoną"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN prijungtas"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN atjungtas"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Per „<xliff:g id="VPN_APP">%1$s</xliff:g>“"</string>
diff --git a/packages/SystemUI/res/values-lt/tiles_states_strings.xml b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
index 4b32820..c881b1e 100644
--- a/packages/SystemUI/res/values-lt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lt/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Išjungta"</item>
     <item msgid="6866424167599381915">"Įjungta"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Nepasiekiama"</item>
     <item msgid="2710157085538036590">"Išjungta"</item>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 50154bc..031f09e 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Lietotne vai jūsu organizācija neatļauj veikt ekrānuzņēmumus."</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Rediģēt"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Rediģēt ekrānuzņēmumu"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Kopīgot ekrānuzņēmumu"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Tvert vairāk"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Nerādīt ekrānuzņēmumu"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekrānuzņēmuma priekšskatījums"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Tālruņa numurs"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Balss palīgs"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Maks"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Atbloķēt"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Ierīce ir bloķēta"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Sejas skenēšana"</string>
@@ -468,6 +469,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lai izmantotu, atbloķējiet ekrānu"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ienesot jūsu kartes, radās problēma. Lūdzu, vēlāk mēģiniet vēlreiz."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Bloķēšanas ekrāna iestatījumi"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Darba profils"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Lidojuma režīms"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nākamais signāls (<xliff:g id="WHEN">%1$s</xliff:g>) netiks atskaņots."</string>
diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml
index e343a77..5eaffaa 100644
--- a/packages/SystemUI/res/values-lv/strings_tv.xml
+++ b/packages/SystemUI/res/values-lv/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofons ir aktīvs"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Lietotne %1$s piekļuva jūsu mikrofonam"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Savienojums ar VPN ir izveidots."</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Savienojums ar VPN ir pārtraukts."</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Izmantojot: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-lv/tiles_states_strings.xml b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
index d000b7c..2f170e0 100644
--- a/packages/SystemUI/res/values-lv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-lv/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Izslēgts"</item>
     <item msgid="6866424167599381915">"Ieslēgts"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Nav pieejams"</item>
     <item msgid="2710157085538036590">"Izslēgts"</item>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 6148344..ad7818a 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликацијата или вашата организација не дозволува снимање слики од екранот"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Измени"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Изменете ја сликата од екранот"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Споделете слика од екранот"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Сними повеќе"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Отфрлете ја сликата од екранот"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Преглед на слика од екранот"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласовна помош"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Паричник"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Отклучување"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Уредот е заклучен"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Скенирање лице"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Отклучете за да користите"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Имаше проблем при преземањето на картичките. Обидете се повторно подоцна"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Поставки за заклучен екран"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Работен профил"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Авионски режим"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Нема да го слушнете следниот аларм <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-mk/strings_tv.xml b/packages/SystemUI/res/values-mk/strings_tv.xml
index f39f1fa..1d0c6a1 100644
--- a/packages/SystemUI/res/values-mk/strings_tv.xml
+++ b/packages/SystemUI/res/values-mk/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Микрофонот е активен"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s пристапи до вашиот микрофон"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN е поврзана"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN е исклучена"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преку <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-mk/tiles_states_strings.xml b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
index 9d0c495..912746a 100644
--- a/packages/SystemUI/res/values-mk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mk/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Исклучено"</item>
     <item msgid="6866424167599381915">"Вклучено"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Недостапно"</item>
     <item msgid="2710157085538036590">"Исклучено"</item>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 28f0238..552d228 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ഫോണ്‍"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"വോയ്‌സ് സഹായം"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"വാലറ്റ്"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"അണ്‍ലോക്ക് ചെയ്യുക"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ഉപകരണം ലോക്ക് ചെയ്തു"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"മുഖം സ്കാൻ ചെയ്യുന്നു"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"നിങ്ങളുടെ കാർഡുകൾ ലഭ്യമാക്കുന്നതിൽ ഒരു പ്രശ്‌നമുണ്ടായി, പിന്നീട് വീണ്ടും ശ്രമിക്കുക"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ലോക്ക് സ്ക്രീൻ ക്രമീകരണം"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ഫ്ലൈറ്റ് മോഡ്"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-നുള്ള നിങ്ങളുടെ അടുത്ത അലാറം കേൾക്കില്ല"</string>
diff --git a/packages/SystemUI/res/values-ml/strings_tv.xml b/packages/SystemUI/res/values-ml/strings_tv.xml
index 50d0280..2bf6902 100644
--- a/packages/SystemUI/res/values-ml/strings_tv.xml
+++ b/packages/SystemUI/res/values-ml/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"മൈക്രോഫോൺ സജീവമാണ്"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s, നിങ്ങളുടെ മൈക്രോഫോൺ ആക്‌സസ് ചെയ്‌തു"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN കണക്റ്റ് ചെയ്‌തു"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN വിച്ഛേദിച്ചു"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> വഴി"</string>
diff --git a/packages/SystemUI/res/values-ml/tiles_states_strings.xml b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
index af2b960..bdbf600 100644
--- a/packages/SystemUI/res/values-ml/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ml/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"ഓഫാണ്"</item>
     <item msgid="6866424167599381915">"ഓണാണ്"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"ലഭ്യമല്ല"</item>
     <item msgid="2710157085538036590">"ഓഫാണ്"</item>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 42bae51..817fc14 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Таны апп, байгууллагад дэлгэцийн зураг авахыг зөвшөөрдөггүй"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Засах"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Дэлгэцийн агшныг засах"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Дэлгэцийн агшныг хуваалцах"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Ихийг багтаасан зураг авах"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Дэлгэцийн агшныг хаах"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Дэлгэцийн агшныг урьдчилан үзэх"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Утас"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Дуут туслах"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Түрийвч"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Тайлах"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Төхөөрөмжийг түгжсэн"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Скан хийх нүүр царай"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ашиглахын тулд түгжээг тайлах"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Таны картыг авахад асуудал гарлаа. Дараа дахин оролдоно уу"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Түгжигдсэн дэлгэцийн тохиргоо"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Ажлын профайл"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Нислэгийн горим"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>-т та дараагийн сэрүүлгээ сонсохгүй"</string>
diff --git a/packages/SystemUI/res/values-mn/strings_tv.xml b/packages/SystemUI/res/values-mn/strings_tv.xml
index 1b20d84..108280c 100644
--- a/packages/SystemUI/res/values-mn/strings_tv.xml
+++ b/packages/SystemUI/res/values-mn/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Микрофон идэвхтэй байна"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s нь таны микрофонд хандcан байна"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN холбогдсон"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN салсан"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g>-р"</string>
diff --git a/packages/SystemUI/res/values-mn/tiles_states_strings.xml b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
index 47a42ff..81b1b1d 100644
--- a/packages/SystemUI/res/values-mn/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mn/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Унтраалттай"</item>
     <item msgid="6866424167599381915">"Асаалттай"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Боломжгүй"</item>
     <item msgid="2710157085538036590">"Унтраалттай"</item>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index f7004b3..ccbf77b 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"फोन"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"व्हॉइस सहाय्य"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"वॉलेट"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"अनलॉक करा"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"डिव्हाइस लॉक केले"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"चेहरा स्कॅन करत आहे"</string>
@@ -438,7 +440,7 @@
     <string name="volume_ringer_status_normal" msgid="1339039682222461143">"रिंग करा"</string>
     <string name="volume_ringer_status_vibrate" msgid="6970078708957857825">"व्हायब्रेट"</string>
     <string name="volume_ringer_status_silent" msgid="3691324657849880883">"म्यूट करा"</string>
-    <string name="volume_stream_content_description_unmute" msgid="7729576371406792977">"%1$s. सशब्द करण्यासाठी टॅप करा."</string>
+    <string name="volume_stream_content_description_unmute" msgid="7729576371406792977">"%1$s. अनम्यूट करण्यासाठी टॅप करा."</string>
     <string name="volume_stream_content_description_vibrate" msgid="4858111994183089761">"%1$s. व्हायब्रेट सेट करण्यासाठी टॅप करा. प्रवेशयोग्यता सेवा म्यूट केल्या जाऊ शकतात."</string>
     <string name="volume_stream_content_description_mute" msgid="4079046784917920984">"%1$s. म्यूट करण्यासाठी टॅप करा. प्रवेशक्षमता सेवा म्यूट केल्या जाऊ शकतात."</string>
     <string name="volume_stream_content_description_vibrate_a11y" msgid="2742330052979397471">"%1$s. व्हायब्रेट सेट करण्यासाठी टॅप करा."</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"वापरण्यासाठी अनलॉक करा"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"तुमची कार्ड मिळवताना समस्या आली, कृपया नंतर पुन्हा प्रयत्न करा"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लॉक स्क्रीन सेटिंग्ज"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाईल"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"विमान मोड"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"तुम्ही तुमचा <xliff:g id="WHEN">%1$s</xliff:g> वाजता होणारा पुढील अलार्म ऐकणार नाही"</string>
diff --git a/packages/SystemUI/res/values-mr/strings_tv.xml b/packages/SystemUI/res/values-mr/strings_tv.xml
index 2d79d4a..0efa4d4 100644
--- a/packages/SystemUI/res/values-mr/strings_tv.xml
+++ b/packages/SystemUI/res/values-mr/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"मायक्रोफोन ॲक्टिव्ह आहे"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s यांनी तुमचा मायक्रोफोन अ‍ॅक्सेस केला आहे"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN कनेक्‍ट केले"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN डिस्कनेक्ट केले"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> द्वारे"</string>
diff --git a/packages/SystemUI/res/values-mr/tiles_states_strings.xml b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
index 4a638b5..560194a 100644
--- a/packages/SystemUI/res/values-mr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-mr/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"बंद आहे"</item>
     <item msgid="6866424167599381915">"सुरू आहे"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"उपलब्ध नाही"</item>
     <item msgid="2710157085538036590">"बंद आहे"</item>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 35ba5a1..82174ab 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -108,6 +108,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Bantuan Suara"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Dompet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Buka kunci"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Peranti dikunci"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Mengimbas wajah"</string>
@@ -465,6 +467,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Buka kunci untuk menggunakan"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Terdapat masalah sewaktu mendapatkan kad anda. Sila cuba sebentar lagi"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Tetapan skrin kunci"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil kerja"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mod pesawat"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Anda tidak akan mendengar penggera yang seterusnya <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ms/strings_tv.xml b/packages/SystemUI/res/values-ms/strings_tv.xml
index 9064ec4..5a8000e 100644
--- a/packages/SystemUI/res/values-ms/strings_tv.xml
+++ b/packages/SystemUI/res/values-ms/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon Aktif"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s telah mengakses mikrofon anda"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN telah disambungkan"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN diputuskan sambungan"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Melalui <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ms/tiles_states_strings.xml b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
index 93d4e6d..fef4b1d 100644
--- a/packages/SystemUI/res/values-ms/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ms/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Mati"</item>
     <item msgid="6866424167599381915">"Hidup"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Tidak tersedia"</item>
     <item msgid="2710157085538036590">"Mati"</item>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index d2722b2..281ad88 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -108,6 +108,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ဖုန်း"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"အသံ အကူအညီ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"သော့ဖွင့်ရန်"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"စက်ပစ္စည်းကို လော့ခ်ချထားသည်"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"မျက်နှာ စကင်ဖတ်နေသည်"</string>
@@ -465,6 +467,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"သုံးရန် လော့ခ်ဖွင့်ပါ"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"သင်၏ကတ်များ ရယူရာတွင် ပြဿနာရှိနေသည်၊ နောက်မှ ထပ်စမ်းကြည့်ပါ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"လော့ခ်မျက်နှာပြင် ဆက်တင်များ"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"အလုပ် ပရိုဖိုင်"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"လေယာဉ်ပျံမုဒ်"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> ၌သင့်နောက်ထပ် နှိုးစက်ကို ကြားမည်မဟုတ်ပါ"</string>
diff --git a/packages/SystemUI/res/values-my/strings_tv.xml b/packages/SystemUI/res/values-my/strings_tv.xml
index 1aca9eb..88a5990 100644
--- a/packages/SystemUI/res/values-my/strings_tv.xml
+++ b/packages/SystemUI/res/values-my/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"မိုက်ခရိုဖုန်း ဖွင့်ထားသည်"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s က သင့်မိုက်ခရိုဖုန်းကို သုံးထားသည်"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ချိတ်ဆက်ထားသည်"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ချိတ်ဆက်မှုမရှိပါ"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> မှတစ်ဆင့်"</string>
diff --git a/packages/SystemUI/res/values-my/tiles_states_strings.xml b/packages/SystemUI/res/values-my/tiles_states_strings.xml
index 3adb16e..898fca3 100644
--- a/packages/SystemUI/res/values-my/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-my/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"ပိတ်"</item>
     <item msgid="6866424167599381915">"ဖွင့်"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"မရနိုင်ပါ"</item>
     <item msgid="2710157085538036590">"ပိတ်"</item>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index a5957cb..3e5f11d 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefonnummer"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Talehjelp"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Lås opp"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Enheten er låst"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skanning av ansikt"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås opp for å bruke"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Det oppsto et problem med henting av kortene. Prøv igjen senere"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Innstillinger for låseskjermen"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Work-profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flymodus"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Du hører ikke neste innstilte alarm <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml
index 7eb6a29..094ab51 100644
--- a/packages/SystemUI/res/values-nb/strings_tv.xml
+++ b/packages/SystemUI/res/values-nb/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofonen er aktiv"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s fikk tilgang til mikrofonen din"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN er tilkoblet"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN er frakoblet"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-nb/tiles_states_strings.xml b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
index 8ebe050..c0e5b3a 100644
--- a/packages/SystemUI/res/values-nb/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nb/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Av"</item>
     <item msgid="6866424167599381915">"På"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Utilgjengelig"</item>
     <item msgid="2710157085538036590">"Av"</item>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 89c66e3..77cdd51 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"फोन"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"आवाज सहायता"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"वालेट"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"खोल्नुहोस्"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"यन्त्र लक गरिएको छ"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"अनुहार स्क्यान गर्दै"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"यो वालेट प्रयोग गर्न डिभाइस अनलक गर्नुहोस्"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"तपाईंका कार्डहरू प्राप्त गर्ने क्रममा समस्या भयो, कृपया पछि फेरि प्रयास गर्नुहोस्"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"लक स्क्रिनसम्बन्धी सेटिङ"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"कार्य प्रोफाइल"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"हवाइजहाज मोड"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"तपाईँले आफ्नो अर्को अलार्म <xliff:g id="WHEN">%1$s</xliff:g> सुन्नुहुने छैन"</string>
diff --git a/packages/SystemUI/res/values-ne/strings_tv.xml b/packages/SystemUI/res/values-ne/strings_tv.xml
index 410f26f..20f1be8 100644
--- a/packages/SystemUI/res/values-ne/strings_tv.xml
+++ b/packages/SystemUI/res/values-ne/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"माइक्रोफोन सक्रिय छ"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ले तपाईंको माइक्रोफोनमाथि पहुँच राख्यो"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN कनेक्ट गरिएको छ"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN डिस्कनेक्ट गरिएको छ"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> मार्फत"</string>
diff --git a/packages/SystemUI/res/values-ne/tiles_states_strings.xml b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
index a1cf9ac..571e128 100644
--- a/packages/SystemUI/res/values-ne/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ne/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"अफ छ"</item>
     <item msgid="6866424167599381915">"अन छ"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"उपलब्ध छैन"</item>
     <item msgid="2710157085538036590">"अफ छ"</item>
diff --git a/packages/SystemUI/res/values-night/styles.xml b/packages/SystemUI/res/values-night/styles.xml
index 07e28b6..cb963e6 100644
--- a/packages/SystemUI/res/values-night/styles.xml
+++ b/packages/SystemUI/res/values-night/styles.xml
@@ -16,9 +16,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Dialog">
-        <item name="android:buttonCornerRadius">28dp</item>
-    </style>
+    <style name="Theme.SystemUI.DayNightDialog" parent="@android:style/Theme.DeviceDefault.Dialog"/>
 
     <style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Dialog.Alert" />
 
@@ -53,13 +51,17 @@
     <style name="TextAppearance.InternetDialog.Active">
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
         <item name="android:textSize">16sp</item>
-        <item name="android:textColor">@color/connected_network_primary_color</item>
+        <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
         <item name="android:textDirection">locale</item>
     </style>
 
     <style name="TextAppearance.InternetDialog.Secondary.Active">
         <item name="android:textSize">14sp</item>
-        <item name="android:textColor">@color/connected_network_secondary_color</item>
+        <item name="android:textColor">?android:attr/textColorSecondaryInverse</item>
+    </style>
+
+    <style name="InternetDialog.Divider.Active">
+        <item name="android:background">?android:attr/textColorSecondaryInverse</item>
     </style>
 
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 530669b..0e8fd0d 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Het maken van screenshots wordt niet toegestaan door de app of je organisatie"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Bewerken"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Screenshot bewerken"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Screenshot delen"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Meer opnemen"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Screenshot sluiten"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Voorbeeld van screenshot"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefoon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Spraakassistent"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portemonnee"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Ontgrendelen"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Apparaat vergrendeld"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Gezicht scannen"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Ontgrendelen om te gebruiken"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Er is een probleem opgetreden bij het ophalen van je kaarten. Probeer het later opnieuw."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Instellingen voor vergrendelscherm"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Werkprofiel"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Vliegtuigmodus"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Je hoort je volgende wekker niet <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
index 7aeeabf..08fdfbf 100644
--- a/packages/SystemUI/res/values-nl/strings_tv.xml
+++ b/packages/SystemUI/res/values-nl/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Microfoon actief"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s heeft toegang tot je microfoon gehad"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Verbinding met VPN"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Geen verbinding met VPN"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-nl/tiles_states_strings.xml b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
index 06b1048..9293f52 100644
--- a/packages/SystemUI/res/values-nl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-nl/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Uit"</item>
     <item msgid="6866424167599381915">"Aan"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Niet beschikbaar"</item>
     <item msgid="2710157085538036590">"Uit"</item>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index bc4e7d1..d02dafb 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ଫୋନ୍‍"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ଭଏସ୍‌ ସହାୟକ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ୱାଲେଟ୍"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"ଅନଲକ୍‌ କରନ୍ତୁ"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ଡିଭାଇସ୍ ଲକ୍ ହୋଇଯାଇଛି"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ଫେସ୍ ସ୍କାନିଙ୍ଗ କରାଯାଉଛି"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ବ୍ୟବହାର କରିବାକୁ ଅନଲକ୍ କରନ୍ତୁ"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"ଆପଣଙ୍କ କାର୍ଡଗୁଡ଼ିକ ପାଇବାରେ ଏକ ସମସ୍ୟା ହୋଇଥିଲା। ଦୟାକରି ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ସ୍କ୍ରିନ୍ ଲକ୍ ସେଟିଂସ୍"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ଏରୋପ୍ଲେନ୍‍ ମୋଡ୍"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g>ବେଳେ ଆପଣ ନିଜର ପରବର୍ତ୍ତୀ ଆଲାର୍ମ ଶୁଣିପାରିବେ ନାହିଁ"</string>
diff --git a/packages/SystemUI/res/values-or/strings_tv.xml b/packages/SystemUI/res/values-or/strings_tv.xml
index 2669a5a..6e6fced 100644
--- a/packages/SystemUI/res/values-or/strings_tv.xml
+++ b/packages/SystemUI/res/values-or/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"ମାଇକ୍ରୋଫୋନ୍ ସକ୍ରିୟ"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ଆପଣଙ୍କର ମାଇକ୍ରୋଫୋନ୍‌କୁ ଆକ୍ସେସ୍ କରିଛି"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ସଂଯୋଗ କରାଯାଇଛି"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ମାଧ୍ୟମରେ"</string>
diff --git a/packages/SystemUI/res/values-or/tiles_states_strings.xml b/packages/SystemUI/res/values-or/tiles_states_strings.xml
index 7129c11..848d382 100644
--- a/packages/SystemUI/res/values-or/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-or/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"ବନ୍ଦ ଅଛି"</item>
     <item msgid="6866424167599381915">"ଚାଲୁ ଅଛି"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"ଉପଲବ୍ଧ ନାହିଁ"</item>
     <item msgid="2710157085538036590">"ବନ୍ଦ ଅଛି"</item>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index de918aa..f3ea051 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ਫ਼ੋਨ ਕਰੋ"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ਅਵਾਜ਼ੀ ਸਹਾਇਕ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"ਵਾਲੇਟ"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"ਡੀਵਾਈਸ ਲਾਕ ਹੈ"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ਚਿਹਰਾ ਸਕੈਨ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"ਤੁਹਾਡੇ ਕਾਰਡ ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਆਈ, ਕਿਰਪਾ ਕਰਕੇ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"ਤੁਸੀਂ <xliff:g id="WHEN">%1$s</xliff:g> ਵਜੇ ਆਪਣਾ ਅਗਲਾ ਅਲਾਰਮ ਨਹੀਂ ਸੁਣੋਗੇ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings_tv.xml b/packages/SystemUI/res/values-pa/strings_tv.xml
index 3443cfa..8483dfb 100644
--- a/packages/SystemUI/res/values-pa/strings_tv.xml
+++ b/packages/SystemUI/res/values-pa/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਕਿਰਿਆਸ਼ੀਲ"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ਨੇ ਤੁਹਾਡੇ ਮਾਈਕ੍ਰੋਫ਼ੋਨ ਤੱਕ ਪਹੁੰਚ ਕੀਤੀ"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ਕਨੈਕਟ ਹੈ"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN ਡਿਸਕਨੈਕਟ ਹੈ"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ਰਾਹੀਂ"</string>
diff --git a/packages/SystemUI/res/values-pa/tiles_states_strings.xml b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
index fbb3888..409b456 100644
--- a/packages/SystemUI/res/values-pa/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pa/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"ਬੰਦ ਹੈ"</item>
     <item msgid="6866424167599381915">"ਚਾਲੂ ਹੈ"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"ਅਣਉਪਲਬਧ ਹੈ"</item>
     <item msgid="2710157085538036590">"ਬੰਦ ਹੈ"</item>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 0245d36..1532645 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asystent głosowy"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Portfel"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Odblokuj"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Urządzenie zablokowane"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skanowanie twarzy"</string>
@@ -470,6 +472,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odblokuj, aby użyć"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Podczas pobierania kart wystąpił problem. Spróbuj ponownie później."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Ustawienia ekranu blokady"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil służbowy"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Tryb samolotowy"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nie usłyszysz swojego następnego alarmu <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml
index 12b3777..e3bcc83 100644
--- a/packages/SystemUI/res/values-pl/strings_tv.xml
+++ b/packages/SystemUI/res/values-pl/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon aktywny"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacja %1$s uzyskała dostęp do mikrofonu"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Połączono z VPN"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Rozłączono z VPN"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Przez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-pl/tiles_states_strings.xml b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
index 1b213b3..2e6df68 100644
--- a/packages/SystemUI/res/values-pl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pl/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Wyłączony"</item>
     <item msgid="6866424167599381915">"Włączony"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Niedostępny"</item>
     <item msgid="2710157085538036590">"Wyłączony"</item>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 75b0b24..226220b 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar captura de tela"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Compartilhar captura de tela"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar mais"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Dispensar captura de tela"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Visualização de captura de tela"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefone"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistência de voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Verificando rosto"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao carregar os cards. Tente novamente mais tarde"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configurações de tela de bloqueio"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Você não ouvirá o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
index d29bc6a..8791d39 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Microfone ativado"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s acessou seu microfone"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
index 5801d30..6647221 100644
--- a/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Desativado"</item>
     <item msgid="6866424167599381915">"Ativado"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Indisponível"</item>
     <item msgid="2710157085538036590">"Desativado"</item>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 94946af..d98900f 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"A app ou a sua entidade não permitem tirar capturas de ecrã"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar captura de ecrã"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Partilhar captura de ecrã"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar mais"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ignorar captura de ecrã"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Pré-visualização da captura de ecrã"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telemóvel"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistente de voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"A analisar o rosto…"</string>
@@ -212,8 +213,8 @@
     <string name="accessibility_clear_all" msgid="970525598287244592">"Limpar todas as notificações."</string>
     <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="91483442850649192">
-      <item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
       <item quantity="one">Mais <xliff:g id="NUMBER_0">%s</xliff:g> notificação no grupo.</item>
+      <item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
     </plurals>
     <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"O ecrã está bloqueado na orientação horizontal."</string>
     <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"O ecrã está bloqueado na orientação vertical."</string>
@@ -262,8 +263,8 @@
     <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"A ativar..."</string>
     <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Poup. dados ativada"</string>
     <plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
-      <item quantity="other">%d dispositivos</item>
       <item quantity="one">%d dispositivo</item>
+      <item quantity="other">%d dispositivos</item>
     </plurals>
     <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lanterna"</string>
     <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Câmara em utilização"</string>
@@ -342,8 +343,8 @@
     <string name="user_add_user_message_short" msgid="2599370307878014791">"Ao adicionar um novo utilizador, essa pessoa tem de configurar o respetivo espaço.\n\nQualquer utilizador pode atualizar apps para todos os outros utilizadores."</string>
     <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite de utilizadores alcançado"</string>
     <plurals name="user_limit_reached_message" formatted="false" msgid="2573535787802908398">
-      <item quantity="other">Pode adicionar até <xliff:g id="COUNT">%d</xliff:g> utilizadores.</item>
       <item quantity="one">Apenas é possível criar um utilizador.</item>
+      <item quantity="other">Pode adicionar até <xliff:g id="COUNT">%d</xliff:g> utilizadores.</item>
     </plurals>
     <string name="user_remove_user_title" msgid="9124124694835811874">"Remover o utilizador?"</string>
     <string name="user_remove_user_message" msgid="6702834122128031833">"Serão eliminados todos os dados e todas as aplicações deste utilizador."</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para utilizar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao obter os seus cartões. Tente novamente mais tarde."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Definições do ecrã de bloqueio"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo de avião"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Não vai ouvir o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
@@ -529,12 +534,12 @@
     <string name="snooze_undo" msgid="2738844148845992103">"Anular"</string>
     <string name="snoozed_for_time" msgid="7586689374860469469">"Suspensa por <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <plurals name="snoozeHourOptions" formatted="false" msgid="2066838694120718170">
-      <item quantity="other">%d horas</item>
       <item quantity="one">%d hora</item>
+      <item quantity="other">%d horas</item>
     </plurals>
     <plurals name="snoozeMinuteOptions" formatted="false" msgid="8998483159208055980">
-      <item quantity="other">%d minutos</item>
       <item quantity="one">%d minuto</item>
+      <item quantity="other">%d minutos</item>
     </plurals>
     <string name="battery_detail_switch_title" msgid="6940976502957380405">"Poupança de bateria"</string>
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botão <xliff:g id="NAME">%1$s</xliff:g>"</string>
@@ -756,8 +761,8 @@
     <string name="quick_controls_title" msgid="6839108006171302273">"Controlos de dispositivos"</string>
     <string name="controls_providers_title" msgid="6879775889857085056">"Escolha uma app para adicionar controlos"</string>
     <plurals name="controls_number_of_favorites" formatted="false" msgid="1057347832073807380">
-      <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlos adicionados.</item>
       <item quantity="one"><xliff:g id="NUMBER_0">%s</xliff:g> controlo adicionado.</item>
+      <item quantity="other"><xliff:g id="NUMBER_1">%s</xliff:g> controlos adicionados.</item>
     </plurals>
     <string name="controls_removed" msgid="3731789252222856959">"Removido"</string>
     <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado aos favoritos"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
index 3ae7daf..c246de0 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Microfone ativado"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s acedeu ao microfone"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está ligada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desligada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Através de <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
index 9ee9fc2..fc3795a 100644
--- a/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Desligado"</item>
     <item msgid="6866424167599381915">"Ligado"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Indisponível"</item>
     <item msgid="2710157085538036590">"Desligado"</item>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 75b0b24..226220b 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"O app ou a organização não permitem capturas de tela"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Editar"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Editar captura de tela"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Compartilhar captura de tela"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Capturar mais"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Dispensar captura de tela"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Visualização de captura de tela"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefone"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Assistência de voz"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Carteira"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Desbloquear"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispositivo bloqueado"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Verificando rosto"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Desbloquear para usar"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Ocorreu um problema ao carregar os cards. Tente novamente mais tarde"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Configurações de tela de bloqueio"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Perfil de trabalho"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modo avião"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Você não ouvirá o próximo alarme às <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml
index d29bc6a..8791d39 100644
--- a/packages/SystemUI/res/values-pt/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Microfone ativado"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s acessou seu microfone"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"A VPN está conectada"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"A VPN está desconectada"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-pt/tiles_states_strings.xml b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
index 5801d30..6647221 100644
--- a/packages/SystemUI/res/values-pt/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-pt/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Desativado"</item>
     <item msgid="6866424167599381915">"Ativado"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Indisponível"</item>
     <item msgid="2710157085538036590">"Desativado"</item>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index d59403e..9e4c7da 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Crearea capturilor de ecran nu este permisă de aplicație sau de organizația dvs."</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Editați"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Editați captura de ecran"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Trimiteți captura de ecran"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Surprindeți mai mult"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Închideți captura de ecran"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Previzualizare a capturii de ecran"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Asistent vocal"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Deblocați"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Dispozitiv blocat"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Scanarea chipului"</string>
@@ -468,6 +469,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Deblocați pentru a folosi"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"A apărut o problemă la preluarea cardurilor. Încercați din nou mai târziu"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Setările ecranului de blocare"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil de serviciu"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Mod Avion"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nu veți auzi următoarea alarmă <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml
index 54dd985..f830f05 100644
--- a/packages/SystemUI/res/values-ro/strings_tv.xml
+++ b/packages/SystemUI/res/values-ro/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Microfon activ"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s a accesat microfonul"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN este conectat"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN este deconectat"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prin <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ro/tiles_states_strings.xml b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
index 3f56424..53d5fa2 100644
--- a/packages/SystemUI/res/values-ro/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ro/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Dezactivat"</item>
     <item msgid="6866424167599381915">"Activat"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Indisponibilă"</item>
     <item msgid="2710157085538036590">"Dezactivată"</item>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 1364c1d..66e32f2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -108,6 +108,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон."</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Аудиоподсказки"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Кошелек"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Разблокировать."</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Устройство заблокировано"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Сканирование лица"</string>
@@ -471,6 +473,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Разблокировать для использования"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Не удалось получить информацию о картах. Повторите попытку позже."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Настройки заблокированного экрана"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Рабочий профиль"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Режим полета"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Следующий будильник: <xliff:g id="WHEN">%1$s</xliff:g>. Звук отключен."</string>
diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml
index befb5d2..877ad9f 100644
--- a/packages/SystemUI/res/values-ru/strings_tv.xml
+++ b/packages/SystemUI/res/values-ru/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Микрофон включен"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Приложение \"%1$s\" использовало доступ к микрофону."</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-подключение установлено"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-подключение отключено"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Через приложение <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ru/tiles_states_strings.xml b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
index 29556da..14098fc 100644
--- a/packages/SystemUI/res/values-ru/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ru/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Откл."</item>
     <item msgid="6866424167599381915">"Вкл."</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Функция недоступна"</item>
     <item msgid="2710157085538036590">"Откл."</item>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index a780614..a25672c 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"දුරකථනය"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"හඬ සහාය"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"පසුම්බිය"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"අඟුල අරින්න"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"උපාංගය අගුලු දමා ඇත"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"මුහුණ ස්කෑන් කිරීම"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"භාවිත කිරීමට අගුලු හරින්න"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"ඔබගේ කාඩ්පත ලබා ගැනීමේ ගැටලුවක් විය, කරුණාකර පසුව නැවත උත්සාහ කරන්න"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"අගුලු තිර සැකසීම්"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"කාර්යාල පැතිකඩ"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ගුවන්යානා ප්‍රකාරය"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"ඔබට ඔබේ ඊළඟ එලාමය <xliff:g id="WHEN">%1$s</xliff:g> නොඇසෙනු ඇත"</string>
diff --git a/packages/SystemUI/res/values-si/strings_tv.xml b/packages/SystemUI/res/values-si/strings_tv.xml
index 92257c7..e9d08ad 100644
--- a/packages/SystemUI/res/values-si/strings_tv.xml
+++ b/packages/SystemUI/res/values-si/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"මයික්‍රොෆෝනය සක්‍රියයි"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ඔබේ මයික්‍රොෆෝනයට ප්‍රවේශ වී ඇත"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN සම්බන්ධිතයි"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN විසන්ධි කර ඇත"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> හරහා"</string>
diff --git a/packages/SystemUI/res/values-si/tiles_states_strings.xml b/packages/SystemUI/res/values-si/tiles_states_strings.xml
index 9ca8198..ed39e4a 100644
--- a/packages/SystemUI/res/values-si/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-si/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"අක්‍රියයි"</item>
     <item msgid="6866424167599381915">"සක්‍රියයි"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"නොමැත"</item>
     <item msgid="2710157085538036590">"අක්‍රියයි"</item>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 5e0b172..4c672bf 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Vytváranie snímok obrazovky je zakázané aplikáciou alebo vašou organizáciou"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Upraviť"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Upraviť snímku obrazovky"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Zdieľať snímku obrazovky"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Zachytiť viac"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Zavrieť snímku obrazovky"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ukážka snímky obrazovky"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefón"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Hlasový asistent"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Peňaženka"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Odomknúť"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Zariadenie je uzamknuté"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Skenovanie tváre"</string>
@@ -471,6 +472,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odomknúť a použiť"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Pri načítavaní kariet sa vyskytol problém. Skúste to neskôr."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavenia uzamknutej obrazovky"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Pracovný profil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Režim v lietadle"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Váš budík o <xliff:g id="WHEN">%1$s</xliff:g> sa nespustí"</string>
diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml
index 6910079..5dd760b 100644
--- a/packages/SystemUI/res/values-sk/strings_tv.xml
+++ b/packages/SystemUI/res/values-sk/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofón je aktívny"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikácia %1$s použila váš mikrofón"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Sieť VPN je pripojená"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Sieť VPN je odpojená"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Cez: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sk/tiles_states_strings.xml b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
index 2e80a80..817e8fb 100644
--- a/packages/SystemUI/res/values-sk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sk/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Vypnuté"</item>
     <item msgid="6866424167599381915">"Zapnuté"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Nie je k dispozícii"</item>
     <item msgid="2710157085538036590">"Vypnuté"</item>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 339bad5..43df9e7 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Glasovni pomočnik"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Google Denarnica"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Odkleni"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Naprava je zaklenjena."</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Optično branje obraza"</string>
@@ -470,6 +472,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Odklenite za uporabo"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Pri pridobivanju kartic je prišlo do težave. Poskusite znova pozneje."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Nastavitve zaklepanja zaslona"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profil za Android Work"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Način za letalo"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Naslednjega alarma ob <xliff:g id="WHEN">%1$s</xliff:g> ne boste slišali"</string>
diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml
index 1005079..4ae7707 100644
--- a/packages/SystemUI/res/values-sl/strings_tv.xml
+++ b/packages/SystemUI/res/values-sl/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon je aktiven"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Aplikacija %1$s je dostopala do mikrofona"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Povezava z omrežjem VPN je vzpostavljena"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Povezava z omrežjem VPN je prekinjena"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Prek storitve <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sl/tiles_states_strings.xml b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
index f1d1aabb..6f6a8f1 100644
--- a/packages/SystemUI/res/values-sl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sl/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Izklopljeno"</item>
     <item msgid="6866424167599381915">"Vklopljeno"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Ni na voljo"</item>
     <item msgid="2710157085538036590">"Izklopljeno"</item>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index bddfcbb..bc9018772 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -108,6 +108,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefoni"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ndihma zanore"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Shkyç"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Pajisja është e kyçur"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Po skanon fytyrën"</string>
@@ -465,6 +467,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Shkyçe për ta përdorur"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Pati një problem me marrjen e kartave të tua. Provo përsëri më vonë"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Cilësimet e ekranit të kyçjes"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profili i punës"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Modaliteti i aeroplanit"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nuk do ta dëgjosh alarmin e radhës në <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sq/strings_tv.xml b/packages/SystemUI/res/values-sq/strings_tv.xml
index c5ce631..3c560ec 100644
--- a/packages/SystemUI/res/values-sq/strings_tv.xml
+++ b/packages/SystemUI/res/values-sq/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofoni aktiv"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s pati qasje te mikrofoni yt"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN-ja është e lidhur"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN-ja është shkëputur"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nëpërmjet <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sq/tiles_states_strings.xml b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
index 83069c9..a88c530 100644
--- a/packages/SystemUI/res/values-sq/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sq/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Joaktiv"</item>
     <item msgid="6866424167599381915">"Aktiv"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Nuk ofrohet"</item>
     <item msgid="2710157085538036590">"Joaktiv"</item>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 5035e8a..0606d0e 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Апликација или организација не дозвољавају прављење снимака екрана"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Измени"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Измените снимак екрана"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Делите снимак екрана"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Снимите још"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Одбаците снимак екрана"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Преглед снимка екрана"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Телефон"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Гласовна помоћ"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Новчаник"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Откључајте"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Уређај је закључан"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Скенирање лица"</string>
@@ -468,6 +469,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Откључај ради коришћења"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Дошло је до проблема при преузимању картица. Пробајте поново касније"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Подешавања закључаног екрана"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Пословни профил"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Режим рада у авиону"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Нећете чути следећи аларм у <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml
index d35ff3c..8ca1057 100644
--- a/packages/SystemUI/res/values-sr/strings_tv.xml
+++ b/packages/SystemUI/res/values-sr/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Микрофон је активан"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Апликација %1$s је приступила микрофону"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN је повезан"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Веза са VPN-ом је прекинута"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Преко: <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sr/tiles_states_strings.xml b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
index cec05da..e2f9c62 100644
--- a/packages/SystemUI/res/values-sr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sr/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Искључено"</item>
     <item msgid="6866424167599381915">"Укључено"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Недоступно"</item>
     <item msgid="2710157085538036590">"Искључено"</item>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 79aac89..60b0097 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Appen eller organisationen tillåter inte att du tar skärmbilder"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Redigera"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Redigera skärmbild"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Dela skärmbild"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Fånga mer"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Stäng skärmbild"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Förhandsgranskning av skärmbild"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Mobil"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Röstassistent"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Lås upp"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Enheten är låst"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Registrerar ansikte"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Lås upp för att använda"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Det gick inte att hämta dina kort. Försök igen senare."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Inställningar för låsskärm"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Jobbprofil"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Flygplansläge"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Nästa alarm, kl. <xliff:g id="WHEN">%1$s</xliff:g>, kommer inte att höras"</string>
diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml
index 346d5d2..8e2e533 100644
--- a/packages/SystemUI/res/values-sv/strings_tv.xml
+++ b/packages/SystemUI/res/values-sv/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofonen är aktiv"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s har fått åtkomst till mikrofonen"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN är anslutet"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN är frånkopplat"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"via <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sv/tiles_states_strings.xml b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
index dbe32da..a7ba12b 100644
--- a/packages/SystemUI/res/values-sv/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sv/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Av"</item>
     <item msgid="6866424167599381915">"På"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Inte tillgängligt"</item>
     <item msgid="2710157085538036590">"Av"</item>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index a4d0118..22e138f 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Programu au shirika lako halikuruhusu kupiga picha za skrini"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Badilisha"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Badilisha picha ya skrini"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Shiriki picha ya skrini"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Nasa zaidi"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ondoa picha ya skrini"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Onyesho la kukagua picha ya skrini"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Simu"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Mapendekezo ya Sauti"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Fungua"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Kifaa kimefungwa"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Inachanganua uso"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Fungua ili utumie"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Hitilafu imetokea wakati wa kuleta kadi zako, tafadhali jaribu tena baadaye"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mipangilio ya kufunga skrini"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Wasifu wa kazini"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Hali ya ndegeni"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Hutasikia kengele yako inayofuata ya saa <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml
index a585e69..d618dbd 100644
--- a/packages/SystemUI/res/values-sw/strings_tv.xml
+++ b/packages/SystemUI/res/values-sw/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Maikrofoni Inatumika"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s imefikia maikrofoni yako"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN imeunganishwa"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN imeondolewa"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Kupitia <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-sw/tiles_states_strings.xml b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
index 93f99b7..f1fbf38 100644
--- a/packages/SystemUI/res/values-sw/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-sw/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Kimezimwa"</item>
     <item msgid="6866424167599381915">"Kimewashwa"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Hakipatikani"</item>
     <item msgid="2710157085538036590">"Kimezimwa"</item>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 430d00b..c2a3ed4 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ஸ்கிரீன் ஷாட்டுகளை எடுப்பதை, ஆப்ஸ் அல்லது உங்கள் நிறுவனம் அனுமதிக்கவில்லை"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"திருத்து"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"ஸ்கிரீன்ஷாட்டைத் திருத்தும்"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"ஸ்கிரீன்ஷாட்டைப் பகிர்"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"கூடுதலாகப் படமெடு"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"ஸ்கிரீன்ஷாட்டை நிராகரிக்கும்"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"ஸ்கிரீன்ஷாட்டின் மாதிரிக்காட்சி"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ஃபோன்"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"குரல் உதவி"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"வாலட்"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"அன்லாக் செய்"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"சாதனம் பூட்டப்பட்டுள்ளது"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"முகத்தை ஸ்கேன் செய்கிறது"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"பயன்படுத்துவதற்கு அன்லாக் செய்க"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"உங்கள் கார்டுகளின் விவரங்களைப் பெறுவதில் சிக்கல் ஏற்பட்டது, பிறகு முயலவும்"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"பூட்டுத் திரை அமைப்புகள்"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"பணிக் கணக்கு"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"விமானப் பயன்முறை"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"அடுத்த அலாரத்தை <xliff:g id="WHEN">%1$s</xliff:g> மணிக்கு கேட்க மாட்டீர்கள்"</string>
diff --git a/packages/SystemUI/res/values-ta/strings_tv.xml b/packages/SystemUI/res/values-ta/strings_tv.xml
index 1dc581d..6e9ee51 100644
--- a/packages/SystemUI/res/values-ta/strings_tv.xml
+++ b/packages/SystemUI/res/values-ta/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"மைக்ரோஃபோன் செயலிலுள்ளது"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s உங்கள் மைக்ரோஃபோனைப் பயன்படுத்தியது"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN இணைக்கப்பட்டது"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN துண்டிக்கப்பட்டது"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> வழியாக"</string>
diff --git a/packages/SystemUI/res/values-ta/tiles_states_strings.xml b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
index d2ba6a5..b2cc840 100644
--- a/packages/SystemUI/res/values-ta/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ta/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"முடக்கப்பட்டுள்ளது"</item>
     <item msgid="6866424167599381915">"இயக்கப்பட்டுள்ளது"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"கிடைக்கவில்லை"</item>
     <item msgid="2710157085538036590">"முடக்கப்பட்டுள்ளது"</item>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index 2c392db..d8a4c21 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"ఫోన్"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"వాయిస్ అసిస్టెంట్"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"వాలెట్"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"అన్‌లాక్ చేయి"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"పరికరం లాక్ చేయబడింది"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"ముఖాన్ని స్కాన్ చేస్తోంది"</string>
@@ -450,7 +452,7 @@
     <string name="volume_dialog_title" msgid="6502703403483577940">"%s వాల్యూమ్ నియంత్రణలు"</string>
     <string name="volume_dialog_ringer_guidance_ring" msgid="9143194270463146858">"కాల్స్‌ మరియు నోటిఫికేషన్‌లు రింగ్ అవుతాయి (<xliff:g id="VOLUME_LEVEL">%1$s</xliff:g>)"</string>
     <string name="system_ui_tuner" msgid="1471348823289954729">"సిస్టమ్ UI ట్యూనర్"</string>
-    <string name="status_bar" msgid="4357390266055077437">"స్థితి పట్టీ"</string>
+    <string name="status_bar" msgid="4357390266055077437">"స్టేటస్‌ పట్టీ"</string>
     <string name="demo_mode" msgid="263484519766901593">"సిస్టమ్ UI డెమో మోడ్"</string>
     <string name="enable_demo_mode" msgid="3180345364745966431">"డెమో మోడ్ ప్రారంభించండి"</string>
     <string name="show_demo_mode" msgid="3677956462273059726">"డెమో మోడ్ చూపు"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ఉపయోగించడానికి అన్‌లాక్ చేయండి"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"మీ కార్డ్‌లను పొందడంలో సమస్య ఉంది, దయచేసి తర్వాత మళ్లీ ట్రై చేయండి"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"లాక్ స్క్రీన్ సెట్టింగ్‌లు"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"ఆఫీస్ ప్రొఫైల్‌"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ఎయిర్‌ప్లేన్ మోడ్"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"మీరు <xliff:g id="WHEN">%1$s</xliff:g> సెట్ చేసిన మీ తర్వాత అలారం మీకు వినిపించదు"</string>
@@ -483,7 +489,7 @@
     <string name="enable_bluetooth_message" msgid="6740938333772779717">"మీ కీబోర్డ్‌ను మీ టాబ్లెట్‌తో కనెక్ట్ చేయడానికి, మీరు ముందుగా బ్లూటూత్ ఆన్ చేయాలి."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="2866408183324184876">"ఆన్ చేయి"</string>
     <string name="tuner_full_importance_settings" msgid="1388025816553459059">"పవర్ నోటిఫికేషన్ నియంత్రణలు"</string>
-    <string name="power_notification_controls_description" msgid="1334963837572708952">"పవర్ నోటిఫికేషన్ నియంత్రణలతో, మీరు యాప్ నోటిఫికేషన్‌ల కోసం ప్రాముఖ్యత స్థాయిని 0 నుండి 5 వరకు సెట్ చేయవచ్చు. \n\n"<b>"స్థాయి 5"</b>" \n- నోటిఫికేషన్ లిస్ట్‌ పైభాగంలో చూపబడతాయి \n- పూర్తి స్క్రీన్ అంతరాయం అనుమతించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 4"</b>\n"- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎల్లప్పుడూ త్వరిత వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 3"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n\n"<b>"స్థాయి 2"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం మరియు వైబ్రేషన్ చేయవు \n\n"<b>"స్థాయి 1"</b>" \n- పూర్తి స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ త్వరిత వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం లేదా వైబ్రేట్ చేయవు \n- లాక్ స్క్రీన్ మరియు స్థితి పట్టీ నుండి దాచబడతాయి \n- నోటిఫికేషన్ లిస్ట్‌ దిగువ భాగంలో చూపబడతాయి \n\n"<b>"స్థాయి 0"</b>" \n- యాప్ నుండి అన్ని నోటిఫికేషన్‌లు బ్లాక్ చేయబడతాయి"</string>
+    <string name="power_notification_controls_description" msgid="1334963837572708952">"పవర్ నోటిఫికేషన్ కంట్రోల్స్ సాయంతో, మీరు యాప్ నోటిఫికేషన్‌లకు ప్రాముఖ్యతా స్థాయిని 0 నుండి 5 వరకు సెట్ చేయవచ్చు. \n\n"<b>"స్థాయి 5"</b>" \n- నోటిఫికేషన్ లిస్ట్‌ పైభాగంలో చూపబడతాయి \n- ఫుల్-స్క్రీన్ అంతరాయం అనుమతించబడుతుంది \n- ఎల్లప్పుడూ క్విక్ వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 4"</b>\n"- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎల్లప్పుడూ క్విక్ వీక్షణ అందించబడుతుంది \n\n"<b>"స్థాయి 3"</b>" \n- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ క్విక్ వీక్షణ అందించబడదు \n\n"<b>"స్థాయి 2"</b>" \n- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ క్విక్ వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం మరియు వైబ్రేషన్ చేయవు \n\n"<b>"స్థాయి 1"</b>" \n- ఫుల్-స్క్రీన్ అంతరాయం నిరోధించబడుతుంది \n- ఎప్పుడూ క్విక్ వీక్షణ అందించబడదు \n- ఎప్పుడూ శబ్దం లేదా వైబ్రేట్ చేయవు \n- లాక్ స్క్రీన్, స్టేటస్ బార్‌ల నుండి దాచబడతాయి \n- నోటిఫికేషన్ లిస్ట్‌ దిగువ భాగంలో చూపబడతాయి \n\n"<b>"స్థాయి 0"</b>" \n- యాప్ నుండి అన్ని నోటిఫికేషన్‌లు బ్లాక్ చేయబడతాయి"</string>
     <string name="inline_done_button" msgid="6043094985588909584">"పూర్తయింది"</string>
     <string name="inline_ok_button" msgid="603075490581280343">"అప్లయి చేయి"</string>
     <string name="inline_turn_off_notifications" msgid="8543989584403106071">"నోటిఫికేషన్‌లను ఆఫ్ చేయి"</string>
@@ -803,7 +809,7 @@
     <string name="controls_error_removed_title" msgid="1207794911208047818">"కంట్రోల్ అందుబాటులో లేదు"</string>
     <string name="controls_error_removed_message" msgid="2885911717034750542">"<xliff:g id="DEVICE">%1$s</xliff:g>ను యాక్సెస్ చేయడం సాధ్యపడలేదు. <xliff:g id="APPLICATION">%2$s</xliff:g> యాప్‌ను తనిఖీ చేసి, కంట్రోల్ ఇప్పటికీ అందుబాటులో ఉందని, యాప్ సెట్టింగ్‌లు మారలేదని నిర్ధారించుకోండి."</string>
     <string name="controls_open_app" msgid="483650971094300141">"యాప్‌ను తెరువు"</string>
-    <string name="controls_error_generic" msgid="352500456918362905">"స్థితిని లోడ్ చేయడం సాధ్యపడదు"</string>
+    <string name="controls_error_generic" msgid="352500456918362905">"స్టేటస్ లోడ్ చేయడం సాధ్యపడలేదు"</string>
     <string name="controls_error_failed" msgid="960228639198558525">"ఎర్రర్, మళ్లీ ప్రయత్నించండి"</string>
     <string name="controls_menu_add" msgid="4447246119229920050">"కంట్రోల్స్‌ను జోడించండి"</string>
     <string name="controls_menu_edit" msgid="890623986951347062">"కంట్రోల్స్‌ను ఎడిట్ చేయండి"</string>
diff --git a/packages/SystemUI/res/values-te/strings_tv.xml b/packages/SystemUI/res/values-te/strings_tv.xml
index 592f8ce..dce274e 100644
--- a/packages/SystemUI/res/values-te/strings_tv.xml
+++ b/packages/SystemUI/res/values-te/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"మైక్రోఫోన్ యాక్టివ్‌గా ఉంది"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"మీ మైక్రోఫోన్‌ను %1$s యాక్సెస్ చేసింది"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN కనెక్ట్ అయింది"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN డిస్‌కనెక్ట్ అయింది"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> ద్వారా"</string>
diff --git a/packages/SystemUI/res/values-te/tiles_states_strings.xml b/packages/SystemUI/res/values-te/tiles_states_strings.xml
index bbe5c8e..3a2dca0 100644
--- a/packages/SystemUI/res/values-te/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-te/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"ఆఫ్‌లో ఉంది"</item>
     <item msgid="6866424167599381915">"ఆన్‌లో ఉంది"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"అందుబాటులో లేదు"</item>
     <item msgid="2710157085538036590">"ఆఫ్‌లో ఉంది"</item>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 8e54bc1..5922678 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -108,6 +108,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"โทรศัพท์"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"ตัวช่วยเสียง"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"ปลดล็อก"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"อุปกรณ์ถูกล็อก"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"กำลังสแกนใบหน้า"</string>
@@ -465,6 +467,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"ปลดล็อกเพื่อใช้"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"เกิดปัญหาในการดึงข้อมูลบัตรของคุณ โปรดลองอีกครั้งในภายหลัง"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"การตั้งค่าหน้าจอล็อก"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"โปรไฟล์งาน"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"โหมดบนเครื่องบิน"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"คุณจะไม่ได้ยินเสียงปลุกครั้งถัดไปในเวลา <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml
index 458dc7e..b00e660 100644
--- a/packages/SystemUI/res/values-th/strings_tv.xml
+++ b/packages/SystemUI/res/values-th/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"ไมโครโฟนเปิดใช้งานอยู่"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s เข้าถึงไมโครโฟนแล้ว"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"เชื่อมต่อ VPN แล้ว"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"ยกเลิกการเชื่อมต่อ VPN แล้ว"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"ผ่าน <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-th/tiles_states_strings.xml b/packages/SystemUI/res/values-th/tiles_states_strings.xml
index 2152e1c..170a9be 100644
--- a/packages/SystemUI/res/values-th/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-th/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"ปิด"</item>
     <item msgid="6866424167599381915">"เปิด"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"ไม่พร้อมใช้งาน"</item>
     <item msgid="2710157085538036590">"ปิด"</item>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 218b21f..05efac2 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -108,6 +108,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telepono"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Voice Assist"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"I-unlock"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Naka-lock ang device"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Sina-scan ang mukha"</string>
@@ -465,6 +467,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"I-unlock para magamit"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Nagkaproblema sa pagkuha ng iyong mga card, pakisubukan ulit sa ibang pagkakataon"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Mga setting ng lock screen"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Profile sa trabaho"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Airplane mode"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Hindi mo maririnig ang iyong susunod na alarm ng <xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml
index b45d62b..88acf87 100644
--- a/packages/SystemUI/res/values-tl/strings_tv.xml
+++ b/packages/SystemUI/res/values-tl/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Aktibo ang Mikropono"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Na-access ng %1$s ang iyong mikropono"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Nakakonekta ang VPN"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Nakadiskonekta ang VPN"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Sa pamamagitan ng <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-tl/tiles_states_strings.xml b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
index 83b9f18..6935782 100644
--- a/packages/SystemUI/res/values-tl/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tl/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Naka-off"</item>
     <item msgid="6866424167599381915">"Naka-on"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Hindi available"</item>
     <item msgid="2710157085538036590">"Naka-off"</item>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 8d1c890..87803f3 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Uygulama veya kuruluşunuz, ekran görüntüsü alınmasına izin vermiyor."</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Düzenle"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Ekran görüntüsünü düzenle"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Ekranı paylaş"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Daha fazla ekran görüntüsü al"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Ekran görüntüsünü kapat"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ekran görüntüsü önizlemesi"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Sesli Yardım"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Cüzdan"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Kilidi aç"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Cihaz kilitlendi"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Yüz taranıyor"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Kullanmak için kilidi aç"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Kartlarınız alınırken bir sorun oluştu. Lütfen daha sonra tekrar deneyin"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Kilit ekranı ayarları"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"İş profili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Uçak modu"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"<xliff:g id="WHEN">%1$s</xliff:g> olarak ayarlanmış bir sonraki alarmınızı duymayacaksınız"</string>
diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml
index 54f24c3..c9580d7f 100644
--- a/packages/SystemUI/res/values-tr/strings_tv.xml
+++ b/packages/SystemUI/res/values-tr/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon Etkin"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s mikrofonunuza erişti"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN bağlandı"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN bağlantısı kesildi"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> üzerinden"</string>
diff --git a/packages/SystemUI/res/values-tr/tiles_states_strings.xml b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
index c550004..34179b5 100644
--- a/packages/SystemUI/res/values-tr/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-tr/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Kapalı"</item>
     <item msgid="6866424167599381915">"Açık"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Kullanılamıyor"</item>
     <item msgid="2710157085538036590">"Kapalı"</item>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index b635714..0dbb0db 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Додаток або адміністратор вашої організації не дозволяють робити знімки екрана"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Редагувати"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Редагувати знімок екрана"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Поділитися знімком екрана"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Включити більше деталей"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Закрити знімок екрана"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Перегляд знімка екрана"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Номер телефону"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Голосові підказки"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Гаманець"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Розблокувати"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Пристрій заблоковано"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Сканування обличчя"</string>
@@ -471,6 +472,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Розблокувати, щоб використовувати"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Не вдалось отримати ваші картки. Повторіть спробу пізніше."</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Параметри блокування екрана"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Робочий профіль"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Режим польоту"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Наступний сигнал о <xliff:g id="WHEN">%1$s</xliff:g> не пролунає"</string>
diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml
index 2ec6d9a..e082884 100644
--- a/packages/SystemUI/res/values-uk/strings_tv.xml
+++ b/packages/SystemUI/res/values-uk/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Мікрофон активовано"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"Додаток %1$s отримав доступ до вашого мікрофона"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"Мережу VPN під\'єднано"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"Мережу VPN від\'єднано"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Через <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-uk/tiles_states_strings.xml b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
index 6420647..21e0128 100644
--- a/packages/SystemUI/res/values-uk/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uk/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Вимкнено"</item>
     <item msgid="6866424167599381915">"Увімкнено"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Недоступно"</item>
     <item msgid="2710157085538036590">"Вимкнено"</item>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index ca50746..1d4b0b0 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"ایپ یا آپ کی تنظیم کی جانب سے اسکرین شاٹس لینے کی اجازت نہیں ہے"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"ترمیم کریں"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"اسکرین شاٹ میں ترمیم کریں"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"اسکرین شاٹ کا اشتراک کریں"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"مزید کیپچر کریں"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"اسکرین شاٹ برخاست کریں"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"اسکرین شاٹ کا پیش منظر"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"فون"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"صوتی معاون"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"غیر مقفل کریں"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"آلہ مقفل کر دیا گیا"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"اسکیننگ چہرہ"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"استعمال کرنے کے لیے غیر مقفل کریں"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"آپ کے کارڈز حاصل کرنے میں ایک مسئلہ درپیش تھا، براہ کرم بعد میں دوبارہ کوشش کریں"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"مقفل اسکرین کی ترتیبات"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"دفتری پروفائل"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"ہوائی جہاز وضع"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"آپ کو <xliff:g id="WHEN">%1$s</xliff:g> بجے اپنا اگلا الارم سنائی نہیں دے گا"</string>
diff --git a/packages/SystemUI/res/values-ur/strings_tv.xml b/packages/SystemUI/res/values-ur/strings_tv.xml
index 566b33f..05e9203 100644
--- a/packages/SystemUI/res/values-ur/strings_tv.xml
+++ b/packages/SystemUI/res/values-ur/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"مائیکروفون فعال ہے"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"‏%1$s نے آپ کے مائیکروفون تک رسائی حاصل کی ہے"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"‏VPN منسلک ہے"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"‏VPN غیر منسلک ہے"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"بذریعہ <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-ur/tiles_states_strings.xml b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
index b8d8cf5..71f2a08 100644
--- a/packages/SystemUI/res/values-ur/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-ur/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"آف ہے"</item>
     <item msgid="6866424167599381915">"آن ہے"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"دستیاب نہیں ہے"</item>
     <item msgid="2710157085538036590">"آف ہے"</item>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index a3955ad..eb02d15 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Telefon"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Ovozli yordam"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Qulfdan chiqarish"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Qurilma qulflandi"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Yuzni skanerlash"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Foydalanish uchun qulfdan chiqarish"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Bildirgilarni yuklashda xatolik yuz berdi, keyinroq qaytadan urining"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Qulflangan ekran sozlamalari"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Ish profili"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Parvoz rejimi"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Keyingi signal (<xliff:g id="WHEN">%1$s</xliff:g>) chalinmaydi"</string>
diff --git a/packages/SystemUI/res/values-uz/strings_tv.xml b/packages/SystemUI/res/values-uz/strings_tv.xml
index afa82bc..acc89b7 100644
--- a/packages/SystemUI/res/values-uz/strings_tv.xml
+++ b/packages/SystemUI/res/values-uz/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Mikrofon faol"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s mikrofondan foydalandi"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN ulandi"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN uzildi"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"<xliff:g id="VPN_APP">%1$s</xliff:g> orqali"</string>
diff --git a/packages/SystemUI/res/values-uz/tiles_states_strings.xml b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
index dad93cb..f69166e 100644
--- a/packages/SystemUI/res/values-uz/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-uz/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Oʻchiq"</item>
     <item msgid="6866424167599381915">"Yoniq"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Ishlamaydi"</item>
     <item msgid="2710157085538036590">"Oʻchiq"</item>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 3396f98..5444f4c 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ứng dụng hoặc tổ chức của bạn không cho phép chụp ảnh màn hình"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Chỉnh sửa"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Chỉnh sửa ảnh chụp màn hình"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Chia sẻ ảnh chụp màn hình"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Chụp thêm"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Đóng ảnh chụp màn hình"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Xem trước ảnh chụp màn hình"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Điện thoại"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Trợ lý thoại"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"Ví"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Mở khóa"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Đã khóa thiết bị"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Quét tìm khuôn mặt"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Mở khóa để sử dụng"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Đã xảy ra sự cố khi tải thẻ của bạn. Vui lòng thử lại sau"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Cài đặt màn hình khóa"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Hồ sơ công việc"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Chế độ máy bay"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Bạn sẽ không nghe thấy báo thức tiếp theo lúc <xliff:g id="WHEN">%1$s</xliff:g> của mình"</string>
diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml
index 0144884..32d18bc 100644
--- a/packages/SystemUI/res/values-vi/strings_tv.xml
+++ b/packages/SystemUI/res/values-vi/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Micrô đang hoạt động"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s đang dùng micrô của bạn"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN đã được kết nối"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN đã bị ngắt kết nối"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Thông qua <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-vi/tiles_states_strings.xml b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
index df16b22..a973ffc 100644
--- a/packages/SystemUI/res/values-vi/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-vi/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Đang tắt"</item>
     <item msgid="6866424167599381915">"Đang bật"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Không hoạt động"</item>
     <item msgid="2710157085538036590">"Đang tắt"</item>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 54c329c..e54fa0d 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"电话"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"语音助理"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"电子钱包"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"解锁"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"设备已锁定"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"正在扫描面孔"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解锁设备即可使用"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"获取您的卡片时出现问题,请稍后重试"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"锁定屏幕设置"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"工作资料"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"飞行模式"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"您在<xliff:g id="WHEN">%1$s</xliff:g>将不会听到下次闹钟响铃"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
index ed914c9..792bf26 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"麦克风处于启用状态"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s访问过您的麦克风"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已连接"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 已断开连接"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"通过“<xliff:g id="VPN_APP">%1$s</xliff:g>”"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
index 0bf0322..e4a6dcd 100644
--- a/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"已关闭"</item>
     <item msgid="6866424167599381915">"已开启"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"不可用"</item>
     <item msgid="2710157085538036590">"已关闭"</item>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index f210619..d791554 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -107,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音助手"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"電子錢包"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"解鎖"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已上鎖"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"掃瞄緊面孔"</string>
@@ -464,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解鎖即可使用"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"擷取資訊卡時發生問題,請稍後再試。"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"上鎖畫面設定"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"工作設定檔"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"飛行模式"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"您不會<xliff:g id="WHEN">%1$s</xliff:g>聽到鬧鐘"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
index dfc34e5..ba1a150 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"麥克風已啟用"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"「%1$s」已存取您的麥克風"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已連線"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 已中斷連線"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過 <xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
index 7339a52..4e6af22 100644
--- a/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"已關閉"</item>
     <item msgid="6866424167599381915">"已開啟"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"無法使用"</item>
     <item msgid="2710157085538036590">"已關閉"</item>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index f96c36a..628e4d4 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"這個應用程式或貴機構不允許擷取螢幕畫面"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"編輯"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"編輯螢幕截圖"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"分享螢幕截圖"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"擴大螢幕截圖範圍"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"關閉螢幕截圖"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"螢幕截圖預覽"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"電話"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"語音小幫手"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"電子錢包"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"解除鎖定"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"裝置已鎖定"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"掃描臉孔"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"解鎖即可使用"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"擷取卡片時發生問題,請稍後再試"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"螢幕鎖定設定"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"工作資料夾"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"飛航模式"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"你不會聽到下一個<xliff:g id="WHEN">%1$s</xliff:g> 的鬧鐘"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
index 869ac48..68cfcfc 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"麥克風已開啟"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"「%1$s」已存取你的麥克風"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"VPN 已連線"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"VPN 連線已中斷"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"透過「<xliff:g id="VPN_APP">%1$s</xliff:g>」"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
index 7339a52..4e6af22 100644
--- a/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"已關閉"</item>
     <item msgid="6866424167599381915">"已開啟"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"無法使用"</item>
     <item msgid="2710157085538036590">"已關閉"</item>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index d06b166..cea362b 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -69,8 +69,7 @@
     <string name="screenshot_failed_to_capture_text" msgid="7818288545874407451">"Ukuthatha izithombe-skrini akuvunyelwe uhlelo lokusebenza noma inhlangano yakho"</string>
     <string name="screenshot_edit_label" msgid="8754981973544133050">"Hlela"</string>
     <string name="screenshot_edit_description" msgid="3333092254706788906">"Hlela isithombe-skrini"</string>
-    <!-- no translation found for screenshot_share_description (2861628935812656612) -->
-    <skip />
+    <string name="screenshot_share_description" msgid="2861628935812656612">"Yabelana ngesithombe-skrini"</string>
     <string name="screenshot_scroll_label" msgid="2930198809899329367">"Thwebula okuningi"</string>
     <string name="screenshot_dismiss_description" msgid="4702341245899508786">"Cashisa isithombe-skrini"</string>
     <string name="screenshot_preview_description" msgid="7606510140714080474">"Ukubuka kuqala isithombe-skrini"</string>
@@ -108,6 +107,8 @@
     <string name="accessibility_phone_button" msgid="4256353121703100427">"Ifoni"</string>
     <string name="accessibility_voice_assist_button" msgid="6497706615649754510">"Isisekeli sezwi"</string>
     <string name="accessibility_wallet_button" msgid="1458258783460555507">"I-wallet"</string>
+    <!-- no translation found for accessibility_qr_code_scanner_button (7521277927692910795) -->
+    <skip />
     <string name="accessibility_unlock_button" msgid="122785427241471085">"Vula"</string>
     <string name="accessibility_lock_icon" msgid="661492842417875775">"Idivayisi ikhiyiwe"</string>
     <string name="accessibility_scanning_face" msgid="3093828357921541387">"Ukuskena ubuso"</string>
@@ -465,6 +466,10 @@
     <string name="wallet_secondary_label_device_locked" msgid="5175862019125370506">"Vula ukuze usebenzise"</string>
     <string name="wallet_error_generic" msgid="257704570182963611">"Kube khona inkinga yokuthola amakhadi akho, sicela uzame futhi ngemuva kwesikhathi"</string>
     <string name="wallet_lockscreen_settings_label" msgid="3539105300870383570">"Amasethingi okukhiya isikrini"</string>
+    <!-- no translation found for qr_code_scanner_title (1598912458255252498) -->
+    <skip />
+    <!-- no translation found for qr_code_scanner_description (7452098243938659945) -->
+    <skip />
     <string name="status_bar_work" msgid="5238641949837091056">"Iphrofayela yomsebenzi"</string>
     <string name="status_bar_airplane" msgid="4848702508684541009">"Imodi yendiza"</string>
     <string name="zen_alarm_warning" msgid="7844303238486849503">"Ngeke uzwe i-alamu yakho elandelayo ngo-<xliff:g id="WHEN">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml
index a3e5255..da6f621 100644
--- a/packages/SystemUI/res/values-zu/strings_tv.xml
+++ b/packages/SystemUI/res/values-zu/strings_tv.xml
@@ -19,8 +19,6 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="mic_active" msgid="5766614241012047024">"Imakrofoni iyasebenza"</string>
-    <string name="app_accessed_mic" msgid="2754428675130470196">"%1$s ifinyelele imakrofoni yakho"</string>
     <string name="notification_vpn_connected" msgid="3891023882833274730">"I-VPN ixhunyiwe"</string>
     <string name="notification_vpn_disconnected" msgid="7150747626448044843">"I-VPN inqanyuliwe"</string>
     <string name="notification_disclosure_vpn_text" msgid="3873532735584866236">"Nge-<xliff:g id="VPN_APP">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-zu/tiles_states_strings.xml b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
index fa2d972..201aa10 100644
--- a/packages/SystemUI/res/values-zu/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values-zu/tiles_states_strings.xml
@@ -151,6 +151,9 @@
     <item msgid="7571394439974244289">"Valiwe"</item>
     <item msgid="6866424167599381915">"Vuliwe"</item>
   </string-array>
+    <!-- no translation found for tile_states_qr_code_scanner:0 (7435143266149257618) -->
+    <!-- no translation found for tile_states_qr_code_scanner:1 (3301403109049256043) -->
+    <!-- no translation found for tile_states_qr_code_scanner:2 (8878684975184010135) -->
   <string-array name="tile_states_alarm">
     <item msgid="4936533380177298776">"Akutholakali"</item>
     <item msgid="2710157085538036590">"Valiwe"</item>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index af5d85d..2b16ec2 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -16,7 +16,8 @@
  * limitations under the License.
  */
 -->
-<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
     <drawable name="notification_number_text_color">#ffffffff</drawable>
     <drawable name="system_bar_background">@color/system_bar_background_opaque</drawable>
     <color name="system_bar_background_opaque">#ff000000</color>
@@ -87,8 +88,6 @@
 
     <color name="notification_section_clear_all_btn_color">@color/GM2_grey_700</color>
 
-    <color name="assist_orb_color">#ffffff</color>
-
     <color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
 
     <!-- The color of the navigation bar icons. Need to be in sync with ic_sysbar_* -->
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 3ed363f..8b59d86 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -82,7 +82,7 @@
 
     <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
     <string name="quick_settings_tiles_stock" translatable="false">
-        internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner
+        internet,bt,flashlight,dnd,alarm,airplane,controls,wallet,rotation,battery,cast,screenrecord,mictoggle,cameratoggle,location,hotspot,inversion,saver,dark,work,night,reverse,reduce_brightness,qr_code_scanner,onehanded,fgsmanager
     </string>
 
     <!-- The tiles to display in QuickSettings -->
@@ -597,6 +597,17 @@
         280
     </integer>
 
+    <!-- Haptic feedback intensity for ticks used for the udfps dwell time -->
+    <item name="config_udfpsTickIntensity" translatable="false" format="float"
+          type="dimen">.5</item>
+
+    <!-- Haptic feedback delay between ticks used for udfps dwell time -->
+    <integer name="config_udfpsTickDelay" translatable="false">25</integer>
+
+    <!-- Haptic feedback tick type - if true, uses VibrationEffect.Composition.PRIMITIVE_LOW_TICK
+         else uses VibrationEffect.Composition.PRIMITIVE_TICK -->
+    <bool name="config_udfpsUseLowTick">true</bool>
+
     <!-- package name of a built-in camera app to use to restrict implicit intent resolution
          when the double-press power gesture is used. Ignored if empty. -->
     <string translatable="false" name="config_cameraGesturePackage"></string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8d0895c..a437ae6 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -678,25 +678,6 @@
          from Keyguard. -->
     <dimen name="go_to_full_shade_appearing_translation">200dp</dimen>
 
-    <!-- The diameter of the search panel circle. -->
-    <dimen name="assist_orb_size">144dp</dimen>
-
-    <!-- The margin to the edge of the screen from where the orb starts to appear -->
-    <dimen name="assist_orb_base_margin">22dp</dimen>
-
-    <!-- The amount the orb translates when appearing -->
-    <dimen name="assist_orb_travel_distance">26dp</dimen>
-
-    <!-- The elevation of the orb -->
-    <dimen name="assist_orb_elevation">12dp</dimen>
-
-    <!-- The height of the scrim behind the orb. -->
-    <dimen name="assist_orb_scrim_height">250dp</dimen>
-
-    <!-- The height of the scrim behind the search panel circle. Should be navigation_bar_height
-         + 8dp. -->
-    <dimen name="assist_orb_navbar_scrim_height">56dp</dimen>
-
     <!-- The width/height of the keyguard bottom area icon view on keyguard. -->
     <dimen name="keyguard_affordance_height">48dp</dimen>
     <dimen name="keyguard_affordance_width">48dp</dimen>
@@ -1104,11 +1085,13 @@
     <!-- Output switcher panel related dimensions -->
     <dimen name="media_output_dialog_list_margin">12dp</dimen>
     <dimen name="media_output_dialog_list_max_height">364dp</dimen>
-    <dimen name="media_output_dialog_header_album_icon_size">48dp</dimen>
+    <dimen name="media_output_dialog_header_album_icon_size">72dp</dimen>
     <dimen name="media_output_dialog_header_back_icon_size">32dp</dimen>
     <dimen name="media_output_dialog_header_icon_padding">16dp</dimen>
-    <dimen name="media_output_dialog_icon_corner_radius">8dp</dimen>
+    <dimen name="media_output_dialog_icon_corner_radius">16dp</dimen>
     <dimen name="media_output_dialog_title_anim_y_delta">12.5dp</dimen>
+    <dimen name="media_output_dialog_button_padding_horizontal">16dp</dimen>
+    <dimen name="media_output_dialog_button_padding_vertical">8dp</dimen>
 
     <!-- Distance that the full shade transition takes in order for qs to fully transition to the
          shade -->
@@ -1259,6 +1242,8 @@
 
     <!-- Internet panel related dimensions -->
     <dimen name="internet_dialog_list_max_height">662dp</dimen>
+    <!-- The height of the WiFi network in Internet panel. -->
+    <dimen name="internet_dialog_wifi_network_height">72dp</dimen>
 
     <!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
     <dimen name="large_dialog_width">@dimen/match_parent</dimen>
@@ -1295,10 +1280,21 @@
     <dimen name="qs_tile_service_request_tile_width">192dp</dimen>
     <dimen name="qs_tile_service_request_content_space">24dp</dimen>
 
-    <dimen name="qs_dialog_button_horizontal_padding">16dp</dimen>
-    <dimen name="qs_dialog_button_vertical_padding">8dp</dimen>
+    <!-- Dimensions for unified SystemUI dialogs styling. Used by Theme.SystemUI.Dialog and
+         alert_dialog_systemui.xml
+      -->
+    <dimen name="dialog_button_horizontal_padding">16dp</dimen>
+    <dimen name="dialog_button_vertical_padding">8dp</dimen>
     <!-- The button will be 48dp tall, but the background needs to be 36dp tall -->
-    <dimen name="qs_dialog_button_vertical_inset">6dp</dimen>
+    <dimen name="dialog_button_vertical_inset">6dp</dimen>
+    <dimen name="dialog_top_padding">24dp</dimen>
+    <dimen name="dialog_bottom_padding">18dp</dimen>
+    <dimen name="dialog_side_padding">24dp</dimen>
+    <dimen name="dialog_button_bar_top_padding">32dp</dimen>
+
+    <!-- ************************************************************************* -->
 
     <dimen name="keyguard_unfold_translation_x">16dp</dimen>
+
+    <dimen name="fgs_manager_min_width_minor">100%</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 937cbed..300cb2d3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -722,6 +722,9 @@
     <!-- QuickSettings: Text to prompt the user to stop an ongoing recording [CHAR LIMIT=20] -->
     <string name="quick_settings_screen_record_stop">Stop</string>
 
+    <!-- QuickSettings: Label for the toggle that controls whether One-handed mode is enabled. [CHAR LIMIT=NONE] -->
+    <string name="quick_settings_onehanded_label">One-handed mode</string>
+
     <!--- Title of dialog triggered if the microphone is disabled but an app tried to access it. [CHAR LIMIT=150] -->
     <string name="sensor_privacy_start_use_mic_dialog_title">Unblock device microphone?</string>
     <!--- Title of dialog triggered if the camera is disabled but an app tried to access it. [CHAR LIMIT=150] -->
@@ -2200,7 +2203,7 @@
     <!-- Summary for disconnected status [CHAR LIMIT=50] -->
     <string name="media_output_dialog_disconnected">(disconnected)</string>
     <!-- Summary for connecting error message [CHAR LIMIT=NONE] -->
-    <string name="media_output_dialog_connect_failed">Couldn\'t connect. Try again.</string>
+    <string name="media_output_dialog_connect_failed">Can\'t switch. Tap to try again.</string>
     <!-- Title for pairing item [CHAR LIMIT=60] -->
     <string name="media_output_dialog_pairing_new">Pair new device</string>
 
@@ -2355,4 +2358,9 @@
 
     <!-- Title for User Switch dialog. [CHAR LIMIT=20] -->
     <string name="qs_user_switch_dialog_title">Select user</string>
+
+    <!-- Title for dialog listing applications currently running in the backing [CHAR LIMIT=NONE]-->
+    <string name="fgs_manager_dialog_title">Apps running in the background</string>
+    <!-- Label of the button to stop the app from running in the background [CHAR LIMIT=12]-->
+    <string name="fgs_manager_app_item_stop_button_label">Stop</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index d972b7fc..12a022d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -14,8 +14,8 @@
      limitations under the License.
 -->
 
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
-    <!-- NOTE: Adding the androidprv: namespace to this file will break the studio build. -->
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+           xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
 
     <!-- HybridNotification themes and styles -->
 
@@ -351,11 +351,19 @@
         <item name="android:windowIsFloating">true</item>
     </style>
 
-    <style name="Theme.SystemUI.Dialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog">
+    <style name="Theme.SystemUI.DayNightDialog" parent="@android:style/Theme.DeviceDefault.Light.Dialog"/>
+
+    <style name="Theme.SystemUI.Dialog" parent="@style/Theme.SystemUI.DayNightDialog">
         <item name="android:buttonCornerRadius">28dp</item>
-        <item name="android:buttonBarPositiveButtonStyle">@style/Widget.QSDialog.Button</item>
-        <item name="android:buttonBarNegativeButtonStyle">@style/Widget.QSDialog.Button.BorderButton</item>
-        <item name="android:buttonBarNeutralButtonStyle">@style/Widget.QSDialog.Button.BorderButton</item>
+        <item name="android:buttonBarPositiveButtonStyle">@style/Widget.Dialog.Button</item>
+        <item name="android:buttonBarNegativeButtonStyle">@style/Widget.Dialog.Button.BorderButton</item>
+        <item name="android:buttonBarNeutralButtonStyle">@style/Widget.Dialog.Button.BorderButton</item>
+        <item name="android:colorBackground">?androidprv:attr/colorSurface</item>
+        <item name="android:alertDialogStyle">@style/AlertDialogStyle</item>
+    </style>
+
+    <style name="AlertDialogStyle" parent="@androidprv:style/AlertDialog.DeviceDefault">
+        <item name="android:layout">@layout/alert_dialog_systemui</item>
     </style>
 
     <style name="Theme.SystemUI.Dialog.Alert" parent="@*android:style/Theme.DeviceDefault.Light.Dialog.Alert" />
@@ -365,11 +373,11 @@
         <item name="android:windowIsFloating">true</item>
     </style>
 
-    <style name="Theme.SystemUI.Dialog.GlobalActionsLite" parent="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen">
-        <item name="android:windowIsFloating">true</item>
+    <style name="Theme.SystemUI.Dialog.GlobalActionsLite" parent="Theme.SystemUI.Dialog">
+        <!-- Settings windowFullscreen: true is necessary to be able to intercept touch events -->
+        <!-- that would otherwise be intercepted by the Shade. -->
+        <item name="android:windowFullscreen">true</item>
         <item name="android:windowBackground">@android:color/transparent</item>
-        <item name="android:backgroundDimEnabled">true</item>
-        <item name="android:windowCloseOnTouchOutside">true</item>
     </style>
 
     <style name="QSBorderlessButton">
@@ -446,6 +454,12 @@
         <item name="android:background">@drawable/media_output_dialog_button_background</item>
     </style>
 
+    <style name="MediaOutputRoundedButton" parent="@android:style/Widget.Material.Button">
+        <item name="android:background">@drawable/media_output_dialog_solid_button_background</item>
+        <item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
+        <item name="android:textSize">14sp</item>
+    </style>
+
     <style name="TunerSettings" parent="@android:style/Theme.DeviceDefault.Settings">
         <item name="android:windowActionBar">false</item>
         <item name="preferenceTheme">@style/TunerPreferenceTheme</item>
@@ -839,7 +853,6 @@
     <style name="Widget.SliceView.Panel">
         <item name="titleSize">16sp</item>
         <item name="rowStyle">@style/SliceRow</item>
-        <item name="android:background">?android:attr/colorBackgroundFloating</item>
     </style>
 
     <style name="SliceRow">
@@ -863,24 +876,37 @@
         <item name="actionDividerHeight">32dp</item>
     </style>
 
-    <style name="TextAppearance.QSDialog.Title" parent="Theme.SystemUI.Dialog">
+    <style name="TextAppearance.Dialog.Title" parent="@android:style/TextAppearance.DeviceDefault.Large">
         <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:textSize">24sp</item>
         <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
         <item name="android:lineHeight">32sp</item>
+        <item name="android:gravity">center</item>
+        <item name="android:textAlignment">center</item>
     </style>
 
-    <style name="Widget.QSDialog.Button" parent = "Theme.SystemUI.Dialog">
+    <style name="TextAppearance.Dialog.Body" parent="@android:style/TextAppearance.DeviceDefault.Medium">
+        <item name="android:textColor">?android:attr/textColorSecondary</item>
+        <item name="android:textSize">14sp</item>
+        <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+        <item name="android:lineHeight">20sp</item>
+    </style>
+
+    <style name="TextAppearance.Dialog.Body.Message">
+        <item name="android:gravity">center</item>
+        <item name="android:textAlignment">center</item>
+    </style>
+
+    <style name="Widget.Dialog.Button" parent = "Theme.SystemUI.Dialog">
         <item name="android:background">@drawable/qs_dialog_btn_filled</item>
-        <item name="android:textColor">@color/prv_text_color_on_accent</item>
+        <item name="android:textColor">?androidprv:attr/textColorOnAccent</item>
         <item name="android:textSize">14sp</item>
         <item name="android:lineHeight">20sp</item>
-        <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
         <item name="android:stateListAnimator">@null</item>
-        <item name="android:layout_marginHorizontal">4dp</item>
     </style>
 
-    <style name="Widget.QSDialog.Button.BorderButton">
+    <style name="Widget.Dialog.Button.BorderButton">
         <item name="android:background">@drawable/qs_dialog_btn_outline</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
@@ -957,4 +983,20 @@
 
     <style name="TextAppearance.InternetDialog.Secondary.Active"/>
 
+    <style name="InternetDialog.Divider">
+        <item name="android:background">?android:attr/textColorSecondary</item>
+    </style>
+
+    <style name="InternetDialog.Divider.Active"/>
+
+    <style name="FgsManagerDialogTitle">
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+        <item name="android:textStyle">bold</item>
+        <item name="android:textDirection">locale</item>
+    </style>
+
+    <style name="FgsManagerAppDuration">
+        <item name="android:fontFamily">?android:attr/textAppearanceSmall</item>
+        <item name="android:textDirection">locale</item>
+    </style>
 </resources>
diff --git a/packages/SystemUI/res/values/tiles_states_strings.xml b/packages/SystemUI/res/values/tiles_states_strings.xml
index 2d51cbe..5fdb497 100644
--- a/packages/SystemUI/res/values/tiles_states_strings.xml
+++ b/packages/SystemUI/res/values/tiles_states_strings.xml
@@ -291,4 +291,21 @@
         <item>Off</item>
         <item>On</item>
     </string-array>
+
+    <!-- State names for One-handed mode tile: unavailable, off, on [CHAR LIMIT=32] -->
+    <string-array name="tile_states_onehanded">
+        <item>Unavailable</item>
+        <item>Off</item>
+        <item>On</item>
+    </string-array>
+
+    <!-- State names for fgsmanager tile: unavailable, off, on.
+         This subtitle is shown when the tile is in that particular state but does not set its own
+         subtitle, so some of these may never appear on screen. They should still be translated as
+         if they could appear.[CHAR LIMIT=32] -->
+    <string-array name="tile_states_fgsmanager">
+        <item>Unavailable</item>
+        <item>Off</item>
+        <item>On</item>
+    </string-array>
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java b/packages/SystemUI/shared/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
index 07ad0c8..8aa3aba 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
@@ -51,6 +51,9 @@
     private static final Interpolator ALPHA_OUT_INTERPOLATOR =
             new PathInterpolator(0f, 0f, 0.8f, 1f);
 
+    @DimenRes
+    private final int mMaxWidthResource;
+
     private Paint mRipplePaint;
     private CanvasProperty<Float> mLeftProp;
     private CanvasProperty<Float> mTopProp;
@@ -90,10 +93,17 @@
     private Type mType = Type.ROUNDED_RECT;
 
     public KeyButtonRipple(Context ctx, View targetView, @DimenRes int maxWidthResource) {
+        mMaxWidthResource = maxWidthResource;
         mMaxWidth = ctx.getResources().getDimensionPixelSize(maxWidthResource);
         mTargetView = targetView;
     }
 
+    public void updateResources() {
+        mMaxWidth = mTargetView.getContext().getResources()
+                .getDimensionPixelSize(mMaxWidthResource);
+        invalidateSelf();
+    }
+
     public void setDarkIntensity(float darkIntensity) {
         mDark = darkIntensity >= 0.5f;
     }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 8bd0f91..0149751 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -95,4 +95,9 @@
      * Sent when screen turned on and ready to use (blocker scrim is hidden)
      */
     void onScreenTurnedOn() = 21;
+
+    /**
+     * Sent when the desired dark intensity of the nav buttons has changed
+     */
+    void onNavButtonsDarkIntensityChanged(float darkIntensity) = 22;
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
index 3128ffd..675dc9b5 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/Task.java
@@ -28,6 +28,7 @@
 import android.os.Parcelable;
 import android.view.ViewDebug;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import java.io.PrintWriter;
@@ -50,6 +51,7 @@
         @ViewDebug.ExportedProperty(category="recents")
         public int windowingMode;
         @ViewDebug.ExportedProperty(category="recents")
+        @NonNull
         public final Intent baseIntent;
         @ViewDebug.ExportedProperty(category="recents")
         public final int userId;
@@ -83,7 +85,7 @@
             updateHashCode();
         }
 
-        public TaskKey(int id, int windowingMode, Intent intent,
+        public TaskKey(int id, int windowingMode, @NonNull Intent intent,
                 ComponentName sourceComponent, int userId, long lastActiveTime) {
             this.id = id;
             this.windowingMode = windowingMode;
@@ -95,7 +97,7 @@
             updateHashCode();
         }
 
-        public TaskKey(int id, int windowingMode, Intent intent,
+        public TaskKey(int id, int windowingMode, @NonNull Intent intent,
                 ComponentName sourceComponent, int userId, long lastActiveTime, int displayId) {
             this.id = id;
             this.windowingMode = windowingMode;
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
index 6154d84..8d98a75 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/utilities/Utilities.java
@@ -18,7 +18,6 @@
 
 import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
 import static android.app.StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
-import static android.util.DisplayMetrics.DENSITY_DEVICE_STABLE;
 
 import android.annotation.TargetApi;
 import android.content.Context;
@@ -126,10 +125,9 @@
         final WindowManager windowManager = context.getSystemService(WindowManager.class);
         final Rect bounds = windowManager.getCurrentWindowMetrics().getBounds();
 
-        float originalSmallestWidth = dpiFromPx(Math.min(bounds.width(), bounds.height()),
+        float smallestWidth = dpiFromPx(Math.min(bounds.width(), bounds.height()),
                 context.getResources().getConfiguration().densityDpi);
-        return dpiFromPx(Math.min(bounds.width(), bounds.height()), DENSITY_DEVICE_STABLE)
-                >= TABLET_MIN_DPS && originalSmallestWidth >= TABLET_MIN_DPS;
+        return smallestWidth >= TABLET_MIN_DPS;
     }
 
     public static float dpiFromPx(float size, int densityDpi) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
index cbf7397..857cc462 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButton.java
@@ -21,6 +21,8 @@
 import android.annotation.LayoutRes;
 import android.annotation.StringRes;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ActivityInfo.Config;
 import android.content.res.Resources;
 import android.graphics.PixelFormat;
 import android.graphics.drawable.AnimatedVectorDrawable;
@@ -29,12 +31,12 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
 import android.view.animation.AccelerateDecelerateInterpolator;
 import android.widget.FrameLayout;
 
 import androidx.core.view.OneShotPreDrawListener;
 
-import com.android.systemui.shared.R;
 import com.android.systemui.shared.rotation.FloatingRotationButtonPositionCalculator.Position;
 
 /**
@@ -48,7 +50,21 @@
     private final ViewGroup mKeyButtonContainer;
     private final FloatingRotationButtonView mKeyButtonView;
 
-    private final int mContainerSize;
+    private int mContainerSize;
+    private final Context mContext;
+
+    @StringRes
+    private final int mContentDescriptionResource;
+    @DimenRes
+    private final int mMinMarginResource;
+    @DimenRes
+    private final int mRoundedContentPaddingResource;
+    @DimenRes
+    private final int mTaskbarLeftMarginResource;
+    @DimenRes
+    private final int mTaskbarBottomMarginResource;
+    @DimenRes
+    private final int mButtonDiameterResource;
 
     private AnimatedVectorDrawable mAnimatedDrawable;
     private boolean mIsShowing;
@@ -58,13 +74,13 @@
     private boolean mIsTaskbarVisible = false;
     private boolean mIsTaskbarStashed = false;
 
-    private final FloatingRotationButtonPositionCalculator mPositionCalculator;
+    private FloatingRotationButtonPositionCalculator mPositionCalculator;
 
     private RotationButtonController mRotationButtonController;
     private RotationButtonUpdatesCallback mUpdatesCallback;
     private Position mPosition;
 
-    public FloatingRotationButton(Context context, @StringRes int contentDescription,
+    public FloatingRotationButton(Context context, @StringRes int contentDescriptionResource,
             @LayoutRes int layout, @IdRes int keyButtonId, @DimenRes int minMargin,
             @DimenRes int roundedContentPadding, @DimenRes int taskbarLeftMargin,
             @DimenRes int taskbarBottomMargin, @DimenRes int buttonDiameter,
@@ -73,24 +89,37 @@
         mKeyButtonContainer = (ViewGroup) LayoutInflater.from(context).inflate(layout, null);
         mKeyButtonView = mKeyButtonContainer.findViewById(keyButtonId);
         mKeyButtonView.setVisibility(View.VISIBLE);
-        mKeyButtonView.setContentDescription(context.getString(contentDescription));
+        mKeyButtonView.setContentDescription(context.getString(contentDescriptionResource));
         mKeyButtonView.setRipple(rippleMaxWidth);
 
-        Resources res = context.getResources();
+        mContext = context;
+
+        mContentDescriptionResource = contentDescriptionResource;
+        mMinMarginResource = minMargin;
+        mRoundedContentPaddingResource = roundedContentPadding;
+        mTaskbarLeftMarginResource = taskbarLeftMargin;
+        mTaskbarBottomMarginResource = taskbarBottomMargin;
+        mButtonDiameterResource = buttonDiameter;
+
+        updateDimensionResources();
+    }
+
+    private void updateDimensionResources() {
+        Resources res = mContext.getResources();
 
         int defaultMargin = Math.max(
-                res.getDimensionPixelSize(minMargin),
-                res.getDimensionPixelSize(roundedContentPadding));
+                res.getDimensionPixelSize(mMinMarginResource),
+                res.getDimensionPixelSize(mRoundedContentPaddingResource));
 
         int taskbarMarginLeft =
-                res.getDimensionPixelSize(taskbarLeftMargin);
+                res.getDimensionPixelSize(mTaskbarLeftMarginResource);
         int taskbarMarginBottom =
-                res.getDimensionPixelSize(taskbarBottomMargin);
+                res.getDimensionPixelSize(mTaskbarBottomMarginResource);
 
         mPositionCalculator = new FloatingRotationButtonPositionCalculator(defaultMargin,
                 taskbarMarginLeft, taskbarMarginBottom);
 
-        final int diameter = res.getDimensionPixelSize(buttonDiameter);
+        final int diameter = res.getDimensionPixelSize(mButtonDiameterResource);
         mContainerSize = diameter + Math.max(defaultMargin, Math.max(taskbarMarginLeft,
                 taskbarMarginBottom));
     }
@@ -119,32 +148,10 @@
         }
 
         mIsShowing = true;
-        int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 
-        // TODO(b/200103245): add new window type that has z-index above
-        //  TYPE_NAVIGATION_BAR_PANEL as currently it could be below the taskbar which has
-        //  the same window type
-        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                mContainerSize,
-                mContainerSize,
-                0, 0, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, flags,
-                PixelFormat.TRANSLUCENT);
+        final LayoutParams layoutParams = adjustViewPositionAndCreateLayoutParams();
+        mWindowManager.addView(mKeyButtonContainer, layoutParams);
 
-        lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
-        lp.setTitle("FloatingRotationButton");
-        lp.setFitInsetsTypes(0 /*types */);
-
-        mDisplayRotation = mWindowManager.getDefaultDisplay().getRotation();
-        mPosition = mPositionCalculator
-                .calculatePosition(mDisplayRotation, mIsTaskbarVisible, mIsTaskbarStashed);
-
-        lp.gravity = mPosition.getGravity();
-        ((FrameLayout.LayoutParams) mKeyButtonView.getLayoutParams()).gravity =
-                mPosition.getGravity();
-
-        updateTranslation(mPosition, /* animate */ false);
-
-        mWindowManager.addView(mKeyButtonContainer, lp);
         if (mAnimatedDrawable != null) {
             mAnimatedDrawable.reset();
             mAnimatedDrawable.start();
@@ -232,6 +239,53 @@
         }
     }
 
+    /**
+     * Updates resources that could be changed in runtime, should be called on configuration
+     * change with changes diff integer mask
+     * @param configurationChanges - configuration changes with flags from ActivityInfo e.g.
+     * {@link android.content.pm.ActivityInfo#CONFIG_DENSITY}
+     */
+    public void onConfigurationChanged(@Config int configurationChanges) {
+        if ((configurationChanges & ActivityInfo.CONFIG_DENSITY) != 0
+                || (configurationChanges & ActivityInfo.CONFIG_SCREEN_SIZE) != 0) {
+            updateDimensionResources();
+
+            if (mIsShowing) {
+                final LayoutParams layoutParams = adjustViewPositionAndCreateLayoutParams();
+                mWindowManager.updateViewLayout(mKeyButtonContainer, layoutParams);
+            }
+        }
+
+        if ((configurationChanges & ActivityInfo.CONFIG_LOCALE) != 0) {
+            mKeyButtonView.setContentDescription(mContext.getString(mContentDescriptionResource));
+        }
+    }
+
+    private LayoutParams adjustViewPositionAndCreateLayoutParams() {
+        final LayoutParams lp = new LayoutParams(
+                mContainerSize,
+                mContainerSize,
+                /* xpos */ 0, /* ypos */ 0, LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+                LayoutParams.FLAG_NOT_FOCUSABLE,
+                PixelFormat.TRANSLUCENT);
+
+        lp.privateFlags |= LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+        lp.setTitle("FloatingRotationButton");
+        lp.setFitInsetsTypes(/* types */ 0);
+
+        mDisplayRotation = mWindowManager.getDefaultDisplay().getRotation();
+        mPosition = mPositionCalculator
+                .calculatePosition(mDisplayRotation, mIsTaskbarVisible, mIsTaskbarStashed);
+
+        lp.gravity = mPosition.getGravity();
+        ((FrameLayout.LayoutParams) mKeyButtonView.getLayoutParams()).gravity =
+                mPosition.getGravity();
+
+        updateTranslation(mPosition, /* animate */ false);
+
+        return lp;
+    }
+
     private void updateTranslation(Position position, boolean animate) {
         final int translationX = position.getTranslationX();
         final int translationY = position.getTranslationY();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java
index c5f8fc1..a4b6451 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/FloatingRotationButtonView.java
@@ -17,6 +17,8 @@
 package com.android.systemui.shared.rotation;
 
 import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
@@ -37,12 +39,15 @@
     private KeyButtonRipple mRipple;
     private final Paint mOvalBgPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
 
+    private final Configuration mLastConfiguration;
+
     public FloatingRotationButtonView(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
 
     public FloatingRotationButtonView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
+        mLastConfiguration = getResources().getConfiguration();
 
         setClickable(true);
 
@@ -63,6 +68,17 @@
         }
     }
 
+    @Override
+    protected void onConfigurationChanged(Configuration newConfig) {
+        final int changes = mLastConfiguration.updateFrom(newConfig);
+        if ((changes & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
+                || ((changes & ActivityInfo.CONFIG_DENSITY) != 0)) {
+            if (mRipple != null) {
+                mRipple.updateResources();
+            }
+        }
+    }
+
     public void setColors(int lightColor, int darkColor) {
         getDrawable().setColorFilter(new PorterDuffColorFilter(lightColor, PorterDuff.Mode.SRC_IN));
 
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
index 2dbd5de..78867f7 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/rotation/RotationButtonController.java
@@ -481,7 +481,9 @@
      * orientation overview.
      */
     public void setSkipOverrideUserLockPrefsOnce() {
-        mSkipOverrideUserLockPrefsOnce = true;
+        // If live-tile is enabled (recents animation keeps running in overview), there is no
+        // activity switch so the display rotation is not changed, then it is no need to skip.
+        mSkipOverrideUserLockPrefsOnce = !mIsRecentsAnimationRunning;
     }
 
     private boolean shouldOverrideUserLockPrefs(final int rotation) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
index 7729a75..e84b552 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java
@@ -205,20 +205,17 @@
                     @Override
                     @SuppressLint("NewApi")
                     public void run() {
+                        counterLauncher.cleanUp(info.getRootLeash());
+                        counterWallpaper.cleanUp(info.getRootLeash());
+                        // Release surface references now. This is apparently to free GPU memory
+                        // while doing quick operations (eg. during CTS).
+                        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+                            info.getChanges().get(i).getLeash().release();
+                        }
+                        for (int i = leashMap.size() - 1; i >= 0; --i) {
+                            leashMap.valueAt(i).release();
+                        }
                         try {
-                            counterLauncher.cleanUp(info.getRootLeash());
-                            counterWallpaper.cleanUp(info.getRootLeash());
-                            // Release surface references now. This is apparently to free GPU
-                            // memory while doing quick operations (eg. during CTS).
-                            for (int i = 0; i < info.getChanges().size(); ++i) {
-                                info.getChanges().get(i).getLeash().release();
-                            }
-                            SurfaceControl.Transaction t = new SurfaceControl.Transaction();
-                            for (int i = 0; i < leashMap.size(); ++i) {
-                                if (leashMap.keyAt(i) == leashMap.valueAt(i)) continue;
-                                t.remove(leashMap.valueAt(i));
-                            }
-                            t.apply();
                             finishCallback.onTransitionFinished(null /* wct */, null /* sct */);
                         } catch (RemoteException e) {
                             Log.e("ActivityOptionsCompat", "Failed to call app controlled animation"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index 954cf9f..a319b40 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -321,7 +321,7 @@
                     // re-showing it's task).
                     final WindowContainerTransaction wct = new WindowContainerTransaction();
                     final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
-                    for (int i = mPausingTasks.size() - 1; i >= 0; ++i) {
+                    for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
                         // reverse order so that index 0 ends up on top
                         wct.reorder(mPausingTasks.get(i), true /* onTop */);
                         t.show(mInfo.getChange(mPausingTasks.get(i)).getLeash());
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
index bee4d7d..10ceee9 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FlagsModule.kt
@@ -20,16 +20,23 @@
 import android.os.Handler
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.util.settings.SettingsUtilModule
+import dagger.Binds
 import dagger.Module
 import dagger.Provides
 
 @Module(includes = [
     SettingsUtilModule::class
 ])
-object FlagsModule {
-    @JvmStatic
-    @Provides
-    fun provideFlagManager(context: Context, @Main handler: Handler): FlagManager {
-        return FlagManager(context, handler)
+abstract class FlagsModule {
+    @Binds
+    abstract fun bindsFeatureFlagDebug(impl: FeatureFlagsDebug): FeatureFlags
+
+    @Module
+    companion object {
+        @JvmStatic
+        @Provides
+        fun provideFlagManager(context: Context, @Main handler: Handler): FlagManager {
+            return FlagManager(context, handler)
+        }
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
index 7647135..ab9e01e 100644
--- a/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
+++ b/packages/SystemUI/src-release/com/android/systemui/flags/FlagsModule.kt
@@ -16,7 +16,11 @@
 
 package com.android.systemui.flags
 
+import dagger.Binds
 import dagger.Module
 
 @Module
-object FlagsModule
\ No newline at end of file
+abstract class FlagsModule {
+    @Binds
+    abstract fun bindsFeatureFlagRelease(impl: FeatureFlagsRelease): FeatureFlags
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 3d4e896..9238b82 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -11,7 +11,6 @@
 import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.ViewTreeObserver.OnPreDrawListener;
 import android.widget.FrameLayout;
 import android.widget.RelativeLayout;
 
@@ -89,7 +88,6 @@
 
     private int mClockSwitchYAmount;
     @VisibleForTesting boolean mChildrenAreLaidOut = false;
-    private OnPreDrawListener mPreDrawListener;
 
     public KeyguardClockSwitch(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -284,30 +282,21 @@
         // translate them properly
         if (mChildrenAreLaidOut) {
             animateClockChange(clockSize == LARGE);
-            mDisplayedClockSize = clockSize;
-        } else if (mPreDrawListener == null) {
-            mPreDrawListener = () -> {
-                switchToClock(clockSize);
-                getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener);
-                mPreDrawListener = null;
-                return true;
-            };
-            getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
         }
+
+        mDisplayedClockSize = clockSize;
         return true;
     }
 
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
-        mChildrenAreLaidOut = true;
-    }
 
-    void onViewDetached() {
-        if (mPreDrawListener != null) {
-            getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener);
-            mPreDrawListener = null;
+        if (mDisplayedClockSize != null && !mChildrenAreLaidOut) {
+            animateClockChange(mDisplayedClockSize == LARGE);
         }
+
+        mChildrenAreLaidOut = true;
     }
 
     public Paint getPaint() {
@@ -368,5 +357,6 @@
         pw.println("  mDarkAmount: " + mDarkAmount);
         pw.println("  mSupportsDarkText: " + mSupportsDarkText);
         pw.println("  mColorPalette: " + Arrays.toString(mColorPalette));
+        pw.println("  mDisplayedClockSize: " + mDisplayedClockSize);
     }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 905495d..c628d44 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -23,6 +23,8 @@
 
 import android.app.WallpaperManager;
 import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.provider.Settings;
 import android.text.TextUtils;
 import android.view.View;
 import android.view.ViewGroup;
@@ -49,11 +51,13 @@
 import com.android.systemui.statusbar.phone.NotificationIconContainer;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.util.ViewController;
+import com.android.systemui.util.settings.SecureSettings;
 
 import java.util.HashSet;
 import java.util.Locale;
 import java.util.Set;
 import java.util.TimeZone;
+import java.util.concurrent.Executor;
 
 import javax.inject.Inject;
 
@@ -72,6 +76,7 @@
     private final BatteryController mBatteryController;
     private final LockscreenSmartspaceController mSmartspaceController;
     private final Resources mResources;
+    private final SecureSettings mSecureSettings;
 
     /**
      * Clock for both small and large sizes
@@ -109,6 +114,14 @@
     private SmartspaceTransitionController mSmartspaceTransitionController;
 
     private boolean mOnlyClock = false;
+    private Executor mUiExecutor;
+    private boolean mCanShowDoubleLineClock = true;
+    private ContentObserver mDoubleLineClockObserver = new ContentObserver(null) {
+        @Override
+        public void onChange(boolean change) {
+            updateDoubleLineClock();
+        }
+    };
 
     @Inject
     public KeyguardClockSwitchController(
@@ -125,6 +138,8 @@
             LockscreenSmartspaceController smartspaceController,
             KeyguardUnlockAnimationController keyguardUnlockAnimationController,
             SmartspaceTransitionController smartspaceTransitionController,
+            SecureSettings secureSettings,
+            @Main Executor uiExecutor,
             @Main Resources resources) {
         super(keyguardClockSwitch);
         mStatusBarStateController = statusBarStateController;
@@ -138,7 +153,8 @@
         mBypassController = bypassController;
         mSmartspaceController = smartspaceController;
         mResources = resources;
-
+        mSecureSettings = secureSettings;
+        mUiExecutor = uiExecutor;
         mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
         mSmartspaceTransitionController = smartspaceTransitionController;
     }
@@ -223,6 +239,14 @@
             updateClockLayout();
             mSmartspaceTransitionController.setLockscreenSmartspace(mSmartspaceView);
         }
+
+        mSecureSettings.registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK),
+                false, /* notifyForDescendants */
+                mDoubleLineClockObserver
+        );
+
+        updateDoubleLineClock();
     }
 
     int getNotificationIconAreaHeight() {
@@ -236,7 +260,8 @@
         }
         mColorExtractor.removeOnColorsChangedListener(mColorsListener);
         mView.setClockPlugin(null, mStatusBarStateController.getState());
-        mView.onViewDetached();
+
+        mSecureSettings.unregisterContentObserver(mDoubleLineClockObserver);
     }
 
     /**
@@ -268,6 +293,10 @@
      * hidden.
      */
     public void displayClock(@KeyguardClockSwitch.ClockSize int clockSize) {
+        if (!mCanShowDoubleLineClock && clockSize == KeyguardClockSwitch.LARGE) {
+            return;
+        }
+
         boolean appeared = mView.switchToClock(clockSize);
         if (appeared && clockSize == LARGE) {
             mLargeClockViewController.animateAppear();
@@ -410,4 +439,13 @@
     private int getCurrentLayoutDirection() {
         return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault());
     }
+
+    private void updateDoubleLineClock() {
+        mCanShowDoubleLineClock = mSecureSettings.getInt(
+            Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1) != 0;
+
+        if (!mCanShowDoubleLineClock) {
+            mUiExecutor.execute(() -> displayClock(KeyguardClockSwitch.SMALL));
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
index 3ebd652..986f296 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostViewController.java
@@ -479,9 +479,7 @@
 
         Resources resources = mView.getResources();
 
-        if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)
-                && resources.getBoolean(
-                com.android.internal.R.bool.config_enableDynamicKeyguardPositioning)) {
+        if (resources.getBoolean(R.bool.can_use_one_handed_bouncer)) {
             gravity = resources.getInteger(
                     R.integer.keyguard_host_view_one_handed_gravity);
         } else {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
index e960e81..03f04d3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt
@@ -38,10 +38,8 @@
     val shouldListenForFingerprintAssistant: Boolean,
     val switchingUser: Boolean,
     val udfps: Boolean,
-    val userDoesNotHaveTrust: Boolean,
-    val userNeedsStrongAuth: Boolean
+    val userDoesNotHaveTrust: Boolean
 ) : KeyguardListenModel()
-
 /**
  * Verbose debug information associated with [KeyguardUpdateMonitor.shouldListenForFace].
  */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index abd89b9..172c7f6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -30,6 +30,7 @@
 import android.graphics.Rect;
 import android.provider.Settings;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.MathUtils;
 import android.util.TypedValue;
 import android.view.Gravity;
@@ -37,6 +38,7 @@
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.ViewConfiguration;
+import android.view.ViewGroup;
 import android.view.WindowInsets;
 import android.view.WindowInsetsAnimation;
 import android.view.WindowManager;
@@ -44,6 +46,8 @@
 import android.view.animation.Interpolator;
 import android.widget.FrameLayout;
 
+import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 import androidx.dynamicanimation.animation.DynamicAnimation;
@@ -58,6 +62,7 @@
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.shared.system.SysUiStatsLog;
+import com.android.systemui.util.settings.GlobalSettings;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -67,6 +72,12 @@
     static final int USER_TYPE_WORK_PROFILE = 2;
     static final int USER_TYPE_SECONDARY_USER = 3;
 
+    @IntDef({MODE_DEFAULT, MODE_ONE_HANDED, MODE_USER_SWITCHER})
+    public @interface Mode {}
+    static final int MODE_DEFAULT = 0;
+    static final int MODE_ONE_HANDED = 1;
+    static final int MODE_USER_SWITCHER = 2;
+
     // Bouncer is dismissed due to no security.
     static final int BOUNCER_DISMISS_NONE_SECURITY = 0;
     // Bouncer is dismissed due to pin, password or pattern entered.
@@ -78,6 +89,8 @@
     // Bouncer is dismissed due to sim card unlock code entered.
     static final int BOUNCER_DISMISS_SIM = 4;
 
+    private static final String TAG = "KeyguardSecurityView";
+
     // Make the view move slower than the finger, as if the spring were applying force.
     private static final float TOUCH_Y_MULTIPLIER = 0.25f;
     // How much you need to drag the bouncer to trigger an auth retry (in dps.)
@@ -96,6 +109,7 @@
 
     @VisibleForTesting
     KeyguardSecurityViewFlipper mSecurityViewFlipper;
+    private GlobalSettings mGlobalSettings;
     private AlertDialog mAlertDialog;
     private boolean mSwipeUpToRetry;
 
@@ -110,10 +124,8 @@
     private float mStartTouchY = -1;
     private boolean mDisappearAnimRunning;
     private SwipeListener mSwipeListener;
-
-    private boolean mIsSecurityViewLeftAligned = true;
-    private boolean mOneHandedMode = false;
-    @Nullable private ValueAnimator mRunningOneHandedAnimator;
+    private ModeLogic mModeLogic = new DefaultModeLogic();
+    private @Mode int mCurrentMode = MODE_DEFAULT;
 
     private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
             new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
@@ -260,172 +272,62 @@
         updateBiometricRetry(securityMode, faceAuthEnabled);
     }
 
-    /**
-     * Sets whether this security container is in one handed mode. If so, it will measure its
-     * child SecurityViewFlipper in one half of the screen, and move it when tapping on the opposite
-     * side of the screen.
-     */
-    public void setOneHandedMode(boolean oneHandedMode) {
-        mOneHandedMode = oneHandedMode;
-        updateSecurityViewGravity();
-        updateSecurityViewLocation(false);
+    void initMode(@Mode int mode, GlobalSettings globalSettings) {
+        if (mCurrentMode == mode) return;
+        Log.i(TAG, "Switching mode from " + modeToString(mCurrentMode) + " to "
+                + modeToString(mode));
+        mCurrentMode = mode;
+
+        switch (mode) {
+            case MODE_ONE_HANDED:
+                mModeLogic = new OneHandedModeLogic();
+                break;
+            case MODE_USER_SWITCHER:
+                mModeLogic = new UserSwitcherModeLogic();
+                break;
+            default:
+                mModeLogic = new DefaultModeLogic();
+        }
+        mGlobalSettings = globalSettings;
+        finishSetup();
     }
 
-    /** Returns whether this security container is in one-handed mode. */
-    public boolean isOneHandedMode() {
-        return mOneHandedMode;
+    private String modeToString(@Mode int mode) {
+        switch (mode) {
+            case MODE_DEFAULT:
+                return "Default";
+            case MODE_ONE_HANDED:
+                return "OneHanded";
+            case MODE_USER_SWITCHER:
+                return "UserSwitcher";
+            default:
+                throw new IllegalArgumentException("mode: " + mode + " not supported");
+        }
+    }
+
+    private void finishSetup() {
+        if (mSecurityViewFlipper == null || mGlobalSettings == null) return;
+
+        mModeLogic.init(this, mGlobalSettings, mSecurityViewFlipper);
+    }
+
+    @Mode int getMode() {
+        return mCurrentMode;
     }
 
     /**
-     * When in one-handed mode, sets if the inner SecurityViewFlipper should be aligned to the
-     * left-hand side of the screen or not, and whether to animate when moving between the two.
+     * The position of the container can be adjusted based upon a touch at location x. This has
+     * been used in one-handed mode to make sure the bouncer appears on the side of the display
+     * that the user last interacted with.
      */
-    public void setOneHandedModeLeftAligned(boolean leftAligned, boolean animate) {
-        mIsSecurityViewLeftAligned = leftAligned;
-        updateSecurityViewLocation(animate);
+    void updatePositionByTouchX(float x) {
+        mModeLogic.updatePositionByTouchX(x);
     }
 
     /** Returns whether the inner SecurityViewFlipper is left-aligned when in one-handed mode. */
     public boolean isOneHandedModeLeftAligned() {
-        return mIsSecurityViewLeftAligned;
-    }
-
-    private void updateSecurityViewGravity() {
-        if (mSecurityViewFlipper == null) {
-            return;
-        }
-
-        FrameLayout.LayoutParams lp =
-                (FrameLayout.LayoutParams) mSecurityViewFlipper.getLayoutParams();
-
-        if (mOneHandedMode) {
-            lp.gravity = Gravity.LEFT | Gravity.BOTTOM;
-        } else {
-            lp.gravity = Gravity.CENTER_HORIZONTAL;
-        }
-
-        mSecurityViewFlipper.setLayoutParams(lp);
-    }
-
-    /**
-     * Moves the inner security view to the correct location (in one handed mode) with animation.
-     * This is triggered when the user taps on the side of the screen that is not currently occupied
-     * by the security view .
-     */
-    private void updateSecurityViewLocation(boolean animate) {
-        if (mSecurityViewFlipper == null) {
-            return;
-        }
-
-        if (!mOneHandedMode) {
-            mSecurityViewFlipper.setTranslationX(0);
-            return;
-        }
-
-        if (mRunningOneHandedAnimator != null) {
-            mRunningOneHandedAnimator.cancel();
-            mRunningOneHandedAnimator = null;
-        }
-
-        int targetTranslation = mIsSecurityViewLeftAligned
-                ? 0 : (int) (getMeasuredWidth() - mSecurityViewFlipper.getWidth());
-
-        if (animate) {
-            // This animation is a bit fun to implement. The bouncer needs to move, and fade in/out
-            // at the same time. The issue is, the bouncer should only move a short amount (120dp or
-            // so), but obviously needs to go from one side of the screen to the other. This needs a
-            // pretty custom animation.
-            //
-            // This works as follows. It uses a ValueAnimation to simply drive the animation
-            // progress. This animator is responsible for both the translation of the bouncer, and
-            // the current fade. It will fade the bouncer out while also moving it along the 120dp
-            // path. Once the bouncer is fully faded out though, it will "snap" the bouncer closer
-            // to its destination, then fade it back in again. The effect is that the bouncer will
-            // move from 0 -> X while fading out, then (destination - X) -> destination while fading
-            // back in again.
-            // TODO(b/195012405): Make this animation properly abortable.
-            Interpolator positionInterpolator = AnimationUtils.loadInterpolator(
-                    mContext, android.R.interpolator.fast_out_extra_slow_in);
-            Interpolator fadeOutInterpolator = Interpolators.FAST_OUT_LINEAR_IN;
-            Interpolator fadeInInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
-
-            mRunningOneHandedAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
-            mRunningOneHandedAnimator.setDuration(BOUNCER_HANDEDNESS_ANIMATION_DURATION_MS);
-            mRunningOneHandedAnimator.setInterpolator(Interpolators.LINEAR);
-
-            int initialTranslation = (int) mSecurityViewFlipper.getTranslationX();
-            int totalTranslation = (int) getResources().getDimension(
-                    R.dimen.one_handed_bouncer_move_animation_translation);
-
-            final boolean shouldRestoreLayerType = mSecurityViewFlipper.hasOverlappingRendering()
-                    && mSecurityViewFlipper.getLayerType() != View.LAYER_TYPE_HARDWARE;
-            if (shouldRestoreLayerType) {
-                mSecurityViewFlipper.setLayerType(View.LAYER_TYPE_HARDWARE, /* paint= */null);
-            }
-
-            float initialAlpha = mSecurityViewFlipper.getAlpha();
-
-            mRunningOneHandedAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mRunningOneHandedAnimator = null;
-                }
-            });
-            mRunningOneHandedAnimator.addUpdateListener(animation -> {
-                float switchPoint = BOUNCER_HANDEDNESS_ANIMATION_FADE_OUT_PROPORTION;
-                boolean isFadingOut = animation.getAnimatedFraction() < switchPoint;
-
-                int currentTranslation = (int) (positionInterpolator.getInterpolation(
-                        animation.getAnimatedFraction()) * totalTranslation);
-                int translationRemaining = totalTranslation - currentTranslation;
-
-                // Flip the sign if we're going from right to left.
-                if (mIsSecurityViewLeftAligned) {
-                    currentTranslation = -currentTranslation;
-                    translationRemaining = -translationRemaining;
-                }
-
-                if (isFadingOut) {
-                    // The bouncer fades out over the first X%.
-                    float fadeOutFraction = MathUtils.constrainedMap(
-                            /* rangeMin= */1.0f,
-                            /* rangeMax= */0.0f,
-                            /* valueMin= */0.0f,
-                            /* valueMax= */switchPoint,
-                            animation.getAnimatedFraction());
-                    float opacity = fadeOutInterpolator.getInterpolation(fadeOutFraction);
-
-                    // When fading out, the alpha needs to start from the initial opacity of the
-                    // view flipper, otherwise we get a weird bit of jank as it ramps back to 100%.
-                    mSecurityViewFlipper.setAlpha(opacity * initialAlpha);
-
-                    // Animate away from the source.
-                    mSecurityViewFlipper.setTranslationX(initialTranslation + currentTranslation);
-                } else {
-                    // And in again over the remaining (100-X)%.
-                    float fadeInFraction = MathUtils.constrainedMap(
-                            /* rangeMin= */0.0f,
-                            /* rangeMax= */1.0f,
-                            /* valueMin= */switchPoint,
-                            /* valueMax= */1.0f,
-                            animation.getAnimatedFraction());
-
-                    float opacity = fadeInInterpolator.getInterpolation(fadeInFraction);
-                    mSecurityViewFlipper.setAlpha(opacity);
-
-                    // Fading back in, animate towards the destination.
-                    mSecurityViewFlipper.setTranslationX(targetTranslation - translationRemaining);
-                }
-
-                if (animation.getAnimatedFraction() == 1.0f && shouldRestoreLayerType) {
-                    mSecurityViewFlipper.setLayerType(View.LAYER_TYPE_NONE, /* paint= */null);
-                }
-            });
-
-            mRunningOneHandedAnimator.start();
-        } else {
-            mSecurityViewFlipper.setTranslationX(targetTranslation);
-        }
+        return mCurrentMode == MODE_ONE_HANDED
+                && ((OneHandedModeLogic) mModeLogic).isLeftAligned();
     }
 
     public void onPause() {
@@ -526,7 +428,7 @@
                 }
             } else {
                 if (!mIsDragging) {
-                    handleTap(event);
+                    mModeLogic.handleTap(event);
                 }
             }
         }
@@ -541,36 +443,6 @@
         mMotionEventListeners.remove(listener);
     }
 
-    private void handleTap(MotionEvent event) {
-        // If we're using a fullscreen security mode, skip
-        if (!mOneHandedMode) {
-            return;
-        }
-
-        moveBouncerForXCoordinate(event.getX(), /* animate= */true);
-    }
-
-    private void moveBouncerForXCoordinate(float x, boolean animate) {
-        // Did the tap hit the "other" side of the bouncer?
-        if ((mIsSecurityViewLeftAligned && (x > getWidth() / 2f))
-                || (!mIsSecurityViewLeftAligned && (x < getWidth() / 2f))) {
-            mIsSecurityViewLeftAligned = !mIsSecurityViewLeftAligned;
-
-            Settings.Global.putInt(
-                    mContext.getContentResolver(),
-                    Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
-                    mIsSecurityViewLeftAligned ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT
-                            : Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT);
-
-            int keyguardState = mIsSecurityViewLeftAligned
-                    ? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_LEFT
-                    : SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_RIGHT;
-            SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, keyguardState);
-
-            updateSecurityViewLocation(animate);
-        }
-    }
-
     void setSwipeListener(SwipeListener swipeListener) {
         mSwipeListener = swipeListener;
     }
@@ -618,6 +490,8 @@
     public void onFinishInflate() {
         super.onFinishInflate();
         mSecurityViewFlipper = findViewById(R.id.view_flipper);
+
+        finishSetup();
     }
 
     @Override
@@ -685,20 +559,15 @@
         int maxWidth = 0;
         int childState = 0;
 
-        int halfWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
-                MeasureSpec.getSize(widthMeasureSpec) / 2,
-                MeasureSpec.getMode(widthMeasureSpec));
-
         for (int i = 0; i < getChildCount(); i++) {
             final View view = getChildAt(i);
             if (view.getVisibility() != GONE) {
-                if (mOneHandedMode && view == mSecurityViewFlipper) {
-                    measureChildWithMargins(view, halfWidthMeasureSpec, 0,
-                            heightMeasureSpec, 0);
-                } else {
-                    measureChildWithMargins(view, widthMeasureSpec, 0,
-                            heightMeasureSpec, 0);
+                int updatedWidthMeasureSpec = widthMeasureSpec;
+                if (view == mSecurityViewFlipper) {
+                    updatedWidthMeasureSpec = mModeLogic.getChildWidthMeasureSpec(widthMeasureSpec);
                 }
+                measureChildWithMargins(view, updatedWidthMeasureSpec, 0, heightMeasureSpec, 0);
+
                 final LayoutParams lp = (LayoutParams) view.getLayoutParams();
                 maxWidth = Math.max(maxWidth,
                         view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
@@ -726,7 +595,7 @@
 
         // After a layout pass, we need to re-place the inner bouncer, as our bounds may have
         // changed.
-        updateSecurityViewLocation(/* animate= */false);
+        mModeLogic.updateSecurityViewLocation();
     }
 
     void showAlmostAtWipeDialog(int attempts, int remaining, int userType) {
@@ -770,4 +639,264 @@
     public void reset() {
         mDisappearAnimRunning = false;
     }
+
+    /**
+     * Enscapsulates the differences between bouncer modes for the container.
+     */
+    private interface ModeLogic {
+
+        default void init(ViewGroup v, GlobalSettings globalSettings,
+                KeyguardSecurityViewFlipper viewFlipper) {};
+
+        /** Reinitialize the location */
+        default void updateSecurityViewLocation() {};
+
+        /** Alter the ViewFlipper position, based upon a touch outside of it */
+        default void updatePositionByTouchX(float x) {};
+
+        /** A tap on the container, outside of the ViewFlipper */
+        default void handleTap(MotionEvent event) {};
+
+        /** Override to alter the width measure spec to perhaps limit the ViewFlipper size */
+        default int getChildWidthMeasureSpec(int parentWidthMeasureSpec) {
+            return parentWidthMeasureSpec;
+        }
+    }
+
+    private static class DefaultModeLogic implements ModeLogic {
+        private ViewGroup mView;
+        private KeyguardSecurityViewFlipper mViewFlipper;
+
+        @Override
+        public void init(ViewGroup v, GlobalSettings globalSettings,
+                KeyguardSecurityViewFlipper viewFlipper) {
+            mView = v;
+            mViewFlipper = viewFlipper;
+
+            // Reset ViewGroup to default positions
+            updateSecurityViewGroup();
+        }
+
+        private void updateSecurityViewGroup() {
+            FrameLayout.LayoutParams lp =
+                    (FrameLayout.LayoutParams) mViewFlipper.getLayoutParams();
+            lp.gravity = Gravity.CENTER_HORIZONTAL;
+            mViewFlipper.setLayoutParams(lp);
+
+            mViewFlipper.setTranslationX(0);
+        }
+    }
+
+    /**
+     * User switcher mode will display both the current user icon as well as
+     * a user switcher, in both portrait and landscape modes.
+     */
+    private static class UserSwitcherModeLogic implements ModeLogic {
+        private ViewGroup mView;
+
+        @Override
+        public void init(ViewGroup v, GlobalSettings globalSettings,
+                KeyguardSecurityViewFlipper viewFlipper) {
+            mView = v;
+        }
+    }
+
+    /**
+     * Logic to enabled one-handed bouncer mode. Supports animating the bouncer
+     * between alternate sides of the display.
+     */
+    private static class OneHandedModeLogic implements ModeLogic {
+        @Nullable private ValueAnimator mRunningOneHandedAnimator;
+        private ViewGroup mView;
+        private KeyguardSecurityViewFlipper mViewFlipper;
+        private GlobalSettings mGlobalSettings;
+
+        @Override
+        public void init(@NonNull ViewGroup v, @NonNull GlobalSettings globalSettings,
+                @NonNull KeyguardSecurityViewFlipper viewFlipper) {
+            mView = v;
+            mViewFlipper = viewFlipper;
+            mGlobalSettings = globalSettings;
+
+            updateSecurityViewGravity();
+            updateSecurityViewLocation(isLeftAligned(), /* animate= */false);
+        }
+
+        /**
+         * One-handed mode contains the child to half of the available space.
+         */
+        @Override
+        public int getChildWidthMeasureSpec(int parentWidthMeasureSpec) {
+            return MeasureSpec.makeMeasureSpec(
+                    MeasureSpec.getSize(parentWidthMeasureSpec) / 2,
+                    MeasureSpec.getMode(parentWidthMeasureSpec));
+        }
+
+        private void updateSecurityViewGravity() {
+            FrameLayout.LayoutParams lp =
+                    (FrameLayout.LayoutParams) mViewFlipper.getLayoutParams();
+            lp.gravity = Gravity.LEFT | Gravity.BOTTOM;
+            mViewFlipper.setLayoutParams(lp);
+        }
+
+        /**
+         * Moves the bouncer to align with a tap (most likely in the shade), so the bouncer
+         * appears on the same side as a touch. Will not update the user-preference.
+         */
+        @Override
+        public void updatePositionByTouchX(float x) {
+            updateSecurityViewLocation(x <= mView.getWidth() / 2f, /* animate= */false);
+        }
+
+        boolean isLeftAligned() {
+            return mGlobalSettings.getInt(Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
+                    Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT)
+                == Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT;
+        }
+
+        /**
+         * Determine if a tap on this view is on the other side. If so, will animate positions
+         * and record the preference to always show on this side.
+         */
+        @Override
+        public void handleTap(MotionEvent event) {
+            float x = event.getX();
+            boolean currentlyLeftAligned = isLeftAligned();
+            // Did the tap hit the "other" side of the bouncer?
+            if ((currentlyLeftAligned && (x > mView.getWidth() / 2f))
+                    || (!currentlyLeftAligned && (x < mView.getWidth() / 2f))) {
+
+                boolean willBeLeftAligned = !currentlyLeftAligned;
+                mGlobalSettings.putInt(
+                        Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
+                        willBeLeftAligned ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT
+                        : Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT);
+
+                int keyguardState = willBeLeftAligned
+                        ? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_LEFT
+                        : SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SWITCH_RIGHT;
+                SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, keyguardState);
+
+                updateSecurityViewLocation(willBeLeftAligned, true /* animate */);
+            }
+        }
+
+        @Override
+        public void updateSecurityViewLocation() {
+            updateSecurityViewLocation(isLeftAligned(), /* animate= */false);
+        }
+
+        /**
+         * Moves the inner security view to the correct location (in one handed mode) with
+         * animation. This is triggered when the user taps on the side of the screen that is not
+         * currently occupied by the security view.
+         */
+        private void updateSecurityViewLocation(boolean leftAlign, boolean animate) {
+            if (mRunningOneHandedAnimator != null) {
+                mRunningOneHandedAnimator.cancel();
+                mRunningOneHandedAnimator = null;
+            }
+
+            int targetTranslation = leftAlign
+                    ? 0 : (int) (mView.getMeasuredWidth() - mViewFlipper.getWidth());
+
+            if (animate) {
+                // This animation is a bit fun to implement. The bouncer needs to move, and fade
+                // in/out at the same time. The issue is, the bouncer should only move a short
+                // amount (120dp or so), but obviously needs to go from one side of the screen to
+                // the other. This needs a pretty custom animation.
+                //
+                // This works as follows. It uses a ValueAnimation to simply drive the animation
+                // progress. This animator is responsible for both the translation of the bouncer,
+                // and the current fade. It will fade the bouncer out while also moving it along the
+                // 120dp path. Once the bouncer is fully faded out though, it will "snap" the
+                // bouncer closer to its destination, then fade it back in again. The effect is that
+                // the bouncer will move from 0 -> X while fading out, then
+                // (destination - X) -> destination while fading back in again.
+                // TODO(b/208250221): Make this animation properly abortable.
+                Interpolator positionInterpolator = AnimationUtils.loadInterpolator(
+                        mView.getContext(), android.R.interpolator.fast_out_extra_slow_in);
+                Interpolator fadeOutInterpolator = Interpolators.FAST_OUT_LINEAR_IN;
+                Interpolator fadeInInterpolator = Interpolators.LINEAR_OUT_SLOW_IN;
+
+                mRunningOneHandedAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
+                mRunningOneHandedAnimator.setDuration(BOUNCER_HANDEDNESS_ANIMATION_DURATION_MS);
+                mRunningOneHandedAnimator.setInterpolator(Interpolators.LINEAR);
+
+                int initialTranslation = (int) mViewFlipper.getTranslationX();
+                int totalTranslation = (int) mView.getResources().getDimension(
+                        R.dimen.one_handed_bouncer_move_animation_translation);
+
+                final boolean shouldRestoreLayerType = mViewFlipper.hasOverlappingRendering()
+                        && mViewFlipper.getLayerType() != View.LAYER_TYPE_HARDWARE;
+                if (shouldRestoreLayerType) {
+                    mViewFlipper.setLayerType(View.LAYER_TYPE_HARDWARE, /* paint= */null);
+                }
+
+                float initialAlpha = mViewFlipper.getAlpha();
+
+                mRunningOneHandedAnimator.addListener(new AnimatorListenerAdapter() {
+                        @Override
+                        public void onAnimationEnd(Animator animation) {
+                            mRunningOneHandedAnimator = null;
+                        }
+                    });
+                mRunningOneHandedAnimator.addUpdateListener(animation -> {
+                    float switchPoint = BOUNCER_HANDEDNESS_ANIMATION_FADE_OUT_PROPORTION;
+                    boolean isFadingOut = animation.getAnimatedFraction() < switchPoint;
+
+                    int currentTranslation = (int) (positionInterpolator.getInterpolation(
+                            animation.getAnimatedFraction()) * totalTranslation);
+                    int translationRemaining = totalTranslation - currentTranslation;
+
+                    // Flip the sign if we're going from right to left.
+                    if (leftAlign) {
+                        currentTranslation = -currentTranslation;
+                        translationRemaining = -translationRemaining;
+                    }
+
+                    if (isFadingOut) {
+                        // The bouncer fades out over the first X%.
+                        float fadeOutFraction = MathUtils.constrainedMap(
+                                /* rangeMin= */1.0f,
+                                /* rangeMax= */0.0f,
+                                /* valueMin= */0.0f,
+                                /* valueMax= */switchPoint,
+                                animation.getAnimatedFraction());
+                        float opacity = fadeOutInterpolator.getInterpolation(fadeOutFraction);
+
+                        // When fading out, the alpha needs to start from the initial opacity of the
+                        // view flipper, otherwise we get a weird bit of jank as it ramps back to
+                        // 100%.
+                        mViewFlipper.setAlpha(opacity * initialAlpha);
+
+                        // Animate away from the source.
+                        mViewFlipper.setTranslationX(initialTranslation + currentTranslation);
+                    } else {
+                        // And in again over the remaining (100-X)%.
+                        float fadeInFraction = MathUtils.constrainedMap(
+                                /* rangeMin= */0.0f,
+                                /* rangeMax= */1.0f,
+                                /* valueMin= */switchPoint,
+                                /* valueMax= */1.0f,
+                                animation.getAnimatedFraction());
+
+                        float opacity = fadeInInterpolator.getInterpolation(fadeInFraction);
+                        mViewFlipper.setAlpha(opacity);
+
+                        // Fading back in, animate towards the destination.
+                        mViewFlipper.setTranslationX(targetTranslation - translationRemaining);
+                    }
+
+                    if (animation.getAnimatedFraction() == 1.0f && shouldRestoreLayerType) {
+                        mViewFlipper.setLayerType(View.LAYER_TYPE_NONE, /* paint= */null);
+                    }
+                });
+
+                mRunningOneHandedAnimator.start();
+            } else {
+                mViewFlipper.setTranslationX(targetTranslation);
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index d4d3d5b..4035229 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -32,7 +32,6 @@
 import android.content.res.Configuration;
 import android.metrics.LogMaker;
 import android.os.UserHandle;
-import android.provider.Settings;
 import android.util.Log;
 import android.util.Slog;
 import android.view.MotionEvent;
@@ -56,6 +55,7 @@
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.ViewController;
+import com.android.systemui.util.settings.GlobalSettings;
 
 import javax.inject.Inject;
 
@@ -78,6 +78,7 @@
     private final SecurityCallback mSecurityCallback;
     private final ConfigurationController mConfigurationController;
     private final FalsingCollector mFalsingCollector;
+    private final GlobalSettings mGlobalSettings;
 
     private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
 
@@ -99,10 +100,10 @@
                 // If we're in one handed mode, the user can tap on the opposite side of the screen
                 // to move the bouncer across. In that case, inhibit the falsing (otherwise the taps
                 // to move the bouncer to each screen side can end up closing it instead).
-                if (mView.isOneHandedMode()) {
-                    if ((mView.isOneHandedModeLeftAligned() && ev.getX() > mView.getWidth() / 2f)
-                            || (!mView.isOneHandedModeLeftAligned()
-                            && ev.getX() <= mView.getWidth() / 2f)) {
+                if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) {
+                    boolean isLeftAligned = mView.isOneHandedModeLeftAligned();
+                    if ((isLeftAligned && ev.getX() > mView.getWidth() / 2f)
+                            || (!isLeftAligned && ev.getX() <= mView.getWidth() / 2f)) {
                         mFalsingCollector.avoidGesture();
                     }
                 }
@@ -152,8 +153,8 @@
 
         public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) {
             int bouncerSide = SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__DEFAULT;
-            if (canUseOneHandedBouncer()) {
-                bouncerSide = isOneHandedKeyguardLeftAligned()
+            if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) {
+                bouncerSide = mView.isOneHandedModeLeftAligned()
                         ? SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__LEFT
                         : SysUiStatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__SIDE__RIGHT;
             }
@@ -230,7 +231,8 @@
             SecurityCallback securityCallback,
             KeyguardSecurityViewFlipperController securityViewFlipperController,
             ConfigurationController configurationController,
-            FalsingCollector falsingCollector) {
+            FalsingCollector falsingCollector,
+            GlobalSettings globalSettings) {
         super(view);
         mLockPatternUtils = lockPatternUtils;
         mUpdateMonitor = keyguardUpdateMonitor;
@@ -245,6 +247,7 @@
         mConfigurationController = configurationController;
         mLastOrientation = getResources().getConfiguration().orientation;
         mFalsingCollector = falsingCollector;
+        mGlobalSettings = globalSettings;
     }
 
     @Override
@@ -324,7 +327,7 @@
     public void onResume(int reason) {
         if (mCurrentSecurityMode != SecurityMode.None) {
             int state = SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN;
-            if (canUseOneHandedBouncer()) {
+            if (mView.getMode() == KeyguardSecurityContainer.MODE_ONE_HANDED) {
                 state = mView.isOneHandedModeLeftAligned()
                         ? SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_LEFT
                         : SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__SHOWN_RIGHT;
@@ -477,47 +480,41 @@
         if (newView != null) {
             newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
             mSecurityViewFlipperController.show(newView);
-            configureOneHandedMode();
+            configureMode();
         }
 
         mSecurityCallback.onSecurityModeChanged(
                 securityMode, newView != null && newView.needsInput());
     }
 
-    /** Read whether the one-handed keyguard should be on the left/right from settings. */
-    private boolean isOneHandedKeyguardLeftAligned() {
-        try {
-            return Settings.Global.getInt(mView.getContext().getContentResolver(),
-                    Settings.Global.ONE_HANDED_KEYGUARD_SIDE)
-                    == Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT;
-        } catch (Settings.SettingNotFoundException ex) {
-            return true;
-        }
-    }
-
+    /**
+     * Returns whether the given security view should be used in a "one handed" way. This can be
+     * used to change how the security view is drawn (e.g. take up less of the screen, and align to
+     * one side).
+     */
     private boolean canUseOneHandedBouncer() {
-        // Is it enabled?
-        if (!getResources().getBoolean(
-                com.android.internal.R.bool.config_enableDynamicKeyguardPositioning)) {
-            return false;
-        }
-
-        if (!KeyguardSecurityModel.isSecurityViewOneHanded(mCurrentSecurityMode)) {
+        if (!(mCurrentSecurityMode == SecurityMode.Pattern
+                || mCurrentSecurityMode == SecurityMode.PIN)) {
             return false;
         }
 
         return getResources().getBoolean(R.bool.can_use_one_handed_bouncer);
     }
 
-    private void configureOneHandedMode() {
-        boolean oneHandedMode = canUseOneHandedBouncer();
+    private boolean canDisplayUserSwitcher() {
+        return getResources().getBoolean(R.bool.bouncer_display_user_switcher);
+    }
 
-        mView.setOneHandedMode(oneHandedMode);
-
-        if (oneHandedMode) {
-            mView.setOneHandedModeLeftAligned(
-                    isOneHandedKeyguardLeftAligned(), /* animate= */false);
+    private void configureMode() {
+        // One-handed mode and user-switcher are currently mutually exclusive, and enforced here
+        int mode = KeyguardSecurityContainer.MODE_DEFAULT;
+        if (canDisplayUserSwitcher()) {
+            mode = KeyguardSecurityContainer.MODE_USER_SWITCHER;
+        } else if (canUseOneHandedBouncer()) {
+            mode = KeyguardSecurityContainer.MODE_ONE_HANDED;
         }
+
+        mView.initMode(mode, mGlobalSettings);
     }
 
     public void reportFailedUnlockAttempt(int userId, int timeoutMs) {
@@ -584,15 +581,13 @@
         int newOrientation = getResources().getConfiguration().orientation;
         if (newOrientation != mLastOrientation) {
             mLastOrientation = newOrientation;
-            configureOneHandedMode();
+            configureMode();
         }
     }
 
     /** Update keyguard position based on a tapped X coordinate. */
     public void updateKeyguardPosition(float x) {
-        if (mView.isOneHandedMode()) {
-            mView.setOneHandedModeLeftAligned(x <= mView.getWidth() / 2f, false);
-        }
+        mView.updatePositionByTouchX(x);
     }
 
     static class Factory {
@@ -609,6 +604,7 @@
         private final KeyguardSecurityViewFlipperController mSecurityViewFlipperController;
         private final ConfigurationController mConfigurationController;
         private final FalsingCollector mFalsingCollector;
+        private final GlobalSettings mGlobalSettings;
 
         @Inject
         Factory(KeyguardSecurityContainer view,
@@ -622,7 +618,8 @@
                 KeyguardStateController keyguardStateController,
                 KeyguardSecurityViewFlipperController securityViewFlipperController,
                 ConfigurationController configurationController,
-                FalsingCollector falsingCollector) {
+                FalsingCollector falsingCollector,
+                GlobalSettings globalSettings) {
             mView = view;
             mAdminSecondaryLockScreenControllerFactory = adminSecondaryLockScreenControllerFactory;
             mLockPatternUtils = lockPatternUtils;
@@ -634,6 +631,7 @@
             mSecurityViewFlipperController = securityViewFlipperController;
             mConfigurationController = configurationController;
             mFalsingCollector = falsingCollector;
+            mGlobalSettings = globalSettings;
         }
 
         public KeyguardSecurityContainerController create(
@@ -642,7 +640,7 @@
                     mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
                     mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
                     mKeyguardStateController, securityCallback, mSecurityViewFlipperController,
-                    mConfigurationController, mFalsingCollector);
+                    mConfigurationController, mFalsingCollector, mGlobalSettings);
         }
 
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
index 69328cd..bacd29f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -94,13 +94,4 @@
                 throw new IllegalStateException("Unknown security quality:" + security);
         }
     }
-
-    /**
-     * Returns whether the given security view should be used in a "one handed" way. This can be
-     * used to change how the security view is drawn (e.g. take up less of the screen, and align to
-     * one side).
-     */
-    public static boolean isSecurityViewOneHanded(SecurityMode securityMode) {
-        return securityMode == SecurityMode.Pattern || securityMode == SecurityMode.PIN;
-    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index d27bc67..b56d189 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -801,13 +801,16 @@
             mHandler.postDelayed(mRetryFingerprintAuthentication, HAL_ERROR_RETRY_TIMEOUT);
         }
 
+        boolean lockedOutStateChanged = false;
         if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
+            lockedOutStateChanged |= !mFingerprintLockedOutPermanent;
             mFingerprintLockedOutPermanent = true;
             requireStrongAuthIfAllLockedOut();
         }
 
         if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
                 || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
+            lockedOutStateChanged |= !mFingerprintLockedOut;
             mFingerprintLockedOut = true;
             if (isUdfpsEnrolled()) {
                 updateFingerprintListeningState();
@@ -820,9 +823,14 @@
                 cb.onBiometricError(msgId, errString, BiometricSourceType.FINGERPRINT);
             }
         }
+
+        if (lockedOutStateChanged) {
+            notifyLockedOutStateChanged(BiometricSourceType.FINGERPRINT);
+        }
     }
 
     private void handleFingerprintLockoutReset() {
+        boolean changed = mFingerprintLockedOut || mFingerprintLockedOutPermanent;
         mFingerprintLockedOut = false;
         mFingerprintLockedOutPermanent = false;
 
@@ -837,6 +845,10 @@
         } else {
             updateFingerprintListeningState();
         }
+
+        if (changed) {
+            notifyLockedOutStateChanged(BiometricSourceType.FINGERPRINT);
+        }
     }
 
     private void setFingerprintRunningState(int fingerprintRunningState) {
@@ -999,7 +1011,9 @@
             }
         }
 
+        boolean lockedOutStateChanged = false;
         if (msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) {
+            lockedOutStateChanged = !mFaceLockedOutPermanent;
             mFaceLockedOutPermanent = true;
             requireStrongAuthIfAllLockedOut();
         }
@@ -1011,11 +1025,21 @@
                         BiometricSourceType.FACE);
             }
         }
+
+        if (lockedOutStateChanged) {
+            notifyLockedOutStateChanged(BiometricSourceType.FACE);
+        }
     }
 
     private void handleFaceLockoutReset() {
+        boolean changed = mFaceLockedOutPermanent;
         mFaceLockedOutPermanent = false;
+
         updateFaceListeningState();
+
+        if (changed) {
+            notifyLockedOutStateChanged(BiometricSourceType.FACE);
+        }
     }
 
     private void setFaceRunningState(int faceRunningState) {
@@ -1237,6 +1261,16 @@
         }
     }
 
+    private void notifyLockedOutStateChanged(BiometricSourceType type) {
+        Assert.isMainThread();
+        for (int i = 0; i < mCallbacks.size(); i++) {
+            KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
+            if (cb != null) {
+                cb.onLockedOutStateChanged(type);
+            }
+        }
+    }
+
     public boolean isScreenOn() {
         return mScreenOn;
     }
@@ -2222,11 +2256,9 @@
                 !(mFingerprintLockedOut && mBouncer && mCredentialAttempted);
 
         final boolean isEncryptedOrLockdownForUser = isEncryptedOrLockdown(user);
-        final boolean userNeedsStrongAuth = userNeedsStrongAuth();
         final boolean shouldListenUdfpsState = !isUdfps
                 || (!userCanSkipBouncer
                     && !isEncryptedOrLockdownForUser
-                    && !userNeedsStrongAuth
                     && userDoesNotHaveTrust
                     && !mFingerprintLockedOut);
 
@@ -2257,8 +2289,7 @@
                         shouldListenForFingerprintAssistant,
                         mSwitchingUser,
                         isUdfps,
-                        userDoesNotHaveTrust,
-                        userNeedsStrongAuth));
+                        userDoesNotHaveTrust));
         }
 
         return shouldListen;
@@ -2362,7 +2393,15 @@
                 || (DEBUG_FINGERPRINT
                     && model instanceof KeyguardFingerprintListenModel
                     && mFingerprintRunningState != BIOMETRIC_STATE_RUNNING);
-        if (notYetRunning && model.getListening()) {
+        final boolean running =
+                (DEBUG_FACE
+                        && model instanceof KeyguardFaceListenModel
+                        && mFaceRunningState == BIOMETRIC_STATE_RUNNING)
+                        || (DEBUG_FINGERPRINT
+                        && model instanceof KeyguardFingerprintListenModel
+                        && mFingerprintRunningState == BIOMETRIC_STATE_RUNNING);
+        if (notYetRunning && model.getListening()
+                || running && !model.getListening()) {
             mListenModels.add(model);
         }
     }
@@ -2449,6 +2488,10 @@
         }
     }
 
+    public boolean isFingerprintLockedOut() {
+        return mFingerprintLockedOut || mFingerprintLockedOutPermanent;
+    }
+
     /**
      * If biometrics hardware is available, not disabled, and user has enrolled templates.
      * This does NOT check if the device is encrypted or in lockdown.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 12431984..8170a81 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -292,6 +292,11 @@
     public void onStrongAuthStateChanged(int userId) { }
 
     /**
+     * When the current user's locked out state changed.
+     */
+    public void onLockedOutStateChanged(BiometricSourceType biometricSourceType) { }
+
+    /**
      * Called when the dream's window state is changed.
      * @param dreaming true if the dream's window has been created and is visible
      */
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconView.java b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
index 68132f4..b2ecc614 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconView.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconView.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.graphics.Color;
 import android.graphics.PointF;
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
@@ -30,6 +31,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
+import com.android.internal.graphics.ColorUtils;
 import com.android.settingslib.Utils;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
@@ -82,14 +84,18 @@
 
     void updateColorAndBackgroundVisibility() {
         if (mUseBackground && mLockIcon.getDrawable() != null) {
-            mLockIconColor = Utils.getColorAttrDefaultColor(getContext(),
-                    android.R.attr.textColorPrimary);
+            mLockIconColor = ColorUtils.blendARGB(
+                    Utils.getColorAttrDefaultColor(getContext(), android.R.attr.textColorPrimary),
+                    Color.WHITE,
+                    mDozeAmount);
             mBgView.setBackground(getContext().getDrawable(R.drawable.fingerprint_bg));
             mBgView.setAlpha(1f - mDozeAmount);
             mBgView.setVisibility(View.VISIBLE);
         } else {
-            mLockIconColor = Utils.getColorAttrDefaultColor(getContext(),
-                    R.attr.wallpaperTextColorAccent);
+            mLockIconColor = ColorUtils.blendARGB(
+                    Utils.getColorAttrDefaultColor(getContext(), R.attr.wallpaperTextColorAccent),
+                    Color.WHITE,
+                    mDozeAmount);
             mBgView.setVisibility(View.GONE);
         }
 
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 8847639..ffa764a 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -33,8 +33,8 @@
 import android.hardware.biometrics.BiometricSourceType;
 import android.hardware.biometrics.SensorLocationInternal;
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
-import android.media.AudioAttributes;
 import android.os.Process;
+import android.os.VibrationAttributes;
 import android.os.Vibrator;
 import android.util.DisplayMetrics;
 import android.util.MathUtils;
@@ -86,11 +86,8 @@
     private static final float sDefaultDensity =
             (float) DisplayMetrics.DENSITY_DEVICE_STABLE / (float) DisplayMetrics.DENSITY_DEFAULT;
     private static final int sLockIconRadiusPx = (int) (sDefaultDensity * 36);
-    private static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
-            new AudioAttributes.Builder()
-                .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-                .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-                .build();
+    private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
+            VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
 
     @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @NonNull private final KeyguardViewController mKeyguardViewController;
@@ -587,7 +584,7 @@
                                 getContext().getOpPackageName(),
                                 UdfpsController.EFFECT_CLICK,
                                 "lockIcon-onDown",
-                                VIBRATION_SONIFICATION_ATTRIBUTES);
+                                TOUCH_VIBRATION_ATTRIBUTES);
                     }
 
                     mDownDetected = true;
@@ -606,7 +603,7 @@
                                 getContext().getOpPackageName(),
                                 UdfpsController.EFFECT_CLICK,
                                 "lockIcon-onLongPress",
-                                VIBRATION_SONIFICATION_ATTRIBUTES);
+                                TOUCH_VIBRATION_ATTRIBUTES);
                     }
                 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index e84024d..33538ec 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -87,7 +87,7 @@
 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.qs.SettingObserver;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.events.PrivacyDotViewController;
 import com.android.systemui.tuner.TunerService;
@@ -155,7 +155,7 @@
     private float mDensity;
     private WindowManager mWindowManager;
     private int mRotation;
-    private SecureSetting mColorInversionSetting;
+    private SettingObserver mColorInversionSetting;
     private DelayableExecutor mExecutor;
     private Handler mHandler;
     private boolean mPendingRotationChange;
@@ -346,7 +346,7 @@
 
             // Watch color inversion and invert the overlay as needed.
             if (mColorInversionSetting == null) {
-                mColorInversionSetting = new SecureSetting(mSecureSettings, mHandler,
+                mColorInversionSetting = new SettingObserver(mSecureSettings, mHandler,
                         Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
                         mUserTracker.getUserId()) {
                     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 43a38aa..8a99728 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -31,8 +31,6 @@
 import com.android.systemui.navigationbar.gestural.BackGestureTfClassifierProvider;
 import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
 import com.android.wm.shell.transition.ShellTransitions;
-import com.android.wm.shell.transition.Transitions;
-import com.android.wm.shell.recents.RecentTasks;
 
 import java.util.Optional;
 import java.util.concurrent.ExecutionException;
@@ -122,7 +120,8 @@
                     .setStartingSurface(mWMComponent.getStartingSurface())
                     .setDisplayAreaHelper(mWMComponent.getDisplayAreaHelper())
                     .setTaskSurfaceHelper(mWMComponent.getTaskSurfaceHelper())
-                    .setRecentTasks(mWMComponent.getRecentTasks());
+                    .setRecentTasks(mWMComponent.getRecentTasks())
+                    .setSizeCompatUI(Optional.of(mWMComponent.getSizeCompatUI()));
         } else {
             // TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option
             // is separating this logic into newly creating SystemUITestsFactory.
@@ -140,7 +139,8 @@
                     .setDisplayAreaHelper(Optional.ofNullable(null))
                     .setStartingSurface(Optional.ofNullable(null))
                     .setTaskSurfaceHelper(Optional.ofNullable(null))
-                    .setRecentTasks(Optional.ofNullable(null));
+                    .setRecentTasks(Optional.ofNullable(null))
+                    .setSizeCompatUI(Optional.ofNullable(null));
         }
         mSysUIComponent = builder.build();
         if (mInitializeComponents) {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java b/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
index c941d66..e4e0da6 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SecureSettingsContentObserver.java
@@ -71,7 +71,9 @@
     public void addListener(@NonNull T listener) {
         Objects.requireNonNull(listener, "listener must be non-null");
 
-        mListeners.add(listener);
+        if (!mListeners.contains(listener)) {
+            mListeners.add(listener);
+        }
 
         if (mListeners.size() == 1) {
             mContentResolver.registerContentObserver(
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
index 33ce206..a10efa9 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnification.java
@@ -68,15 +68,15 @@
     private Configuration mLastConfiguration;
     private SysUiState mSysUiState;
 
-    private static class AnimationControllerSupplier extends
-            DisplayIdIndexSupplier<WindowMagnificationAnimationController> {
+    private static class ControllerSupplier extends
+            DisplayIdIndexSupplier<WindowMagnificationController> {
 
         private final Context mContext;
         private final Handler mHandler;
         private final WindowMagnifierCallback mWindowMagnifierCallback;
         private final SysUiState mSysUiState;
 
-        AnimationControllerSupplier(Context context, Handler handler,
+        ControllerSupplier(Context context, Handler handler,
                 WindowMagnifierCallback windowMagnifierCallback,
                 DisplayManager displayManager, SysUiState sysUiState) {
             super(displayManager);
@@ -87,19 +87,19 @@
         }
 
         @Override
-        protected WindowMagnificationAnimationController createInstance(Display display) {
+        protected WindowMagnificationController createInstance(Display display) {
             final Context windowContext = mContext.createWindowContext(display,
                     TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, /* options */ null);
-            final WindowMagnificationController controller = new WindowMagnificationController(
+            return new WindowMagnificationController(
                     windowContext,
-                    mHandler, new SfVsyncFrameCallbackProvider(), null,
+                    mHandler, new WindowMagnificationAnimationController(windowContext),
+                    new SfVsyncFrameCallbackProvider(), null,
                     new SurfaceControl.Transaction(), mWindowMagnifierCallback, mSysUiState);
-            return new WindowMagnificationAnimationController(windowContext, controller);
         }
     }
 
     @VisibleForTesting
-    DisplayIdIndexSupplier<WindowMagnificationAnimationController> mAnimationControllerSupplier;
+    DisplayIdIndexSupplier<WindowMagnificationController> mMagnificationControllerSupplier;
 
     @Inject
     public WindowMagnification(Context context, @Main Handler mainHandler,
@@ -113,7 +113,7 @@
         mModeSwitchesController = modeSwitchesController;
         mSysUiState = sysUiState;
         mOverviewProxyService = overviewProxyService;
-        mAnimationControllerSupplier = new AnimationControllerSupplier(context,
+        mMagnificationControllerSupplier = new ControllerSupplier(context,
                 mHandler, this, context.getSystemService(DisplayManager.class), sysUiState);
     }
 
@@ -121,8 +121,9 @@
     public void onConfigurationChanged(Configuration newConfig) {
         final int configDiff = newConfig.diff(mLastConfiguration);
         mLastConfiguration.setTo(newConfig);
-        mAnimationControllerSupplier.forEach(
-                animationController -> animationController.onConfigurationChanged(configDiff));
+        mMagnificationControllerSupplier.forEach(
+                magnificationController -> magnificationController.onConfigurationChanged(
+                        configDiff));
         if (mModeSwitchesController != null) {
             mModeSwitchesController.onConfigurationChanged(configDiff);
         }
@@ -143,10 +144,10 @@
 
     private void updateSysUiStateFlag() {
         //TODO(b/187510533): support multi-display once SysuiState supports it.
-        final WindowMagnificationAnimationController controller =
-                mAnimationControllerSupplier.valueAt(Display.DEFAULT_DISPLAY);
+        final WindowMagnificationController controller =
+                mMagnificationControllerSupplier.valueAt(Display.DEFAULT_DISPLAY);
         if (controller != null) {
-            controller.updateSysUiStateFlag();
+            controller.updateSysUIStateFlag();
         } else {
             // The instance is initialized when there is an IPC request. Considering
             // self-crash cases, we need to reset the flag in such situation.
@@ -157,40 +158,41 @@
 
     @MainThread
     void enableWindowMagnification(int displayId, float scale, float centerX, float centerY,
+            float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
             @Nullable IRemoteMagnificationAnimationCallback callback) {
-        final WindowMagnificationAnimationController windowMagnificationAnimationController =
-                mAnimationControllerSupplier.get(displayId);
-        if (windowMagnificationAnimationController != null) {
-            windowMagnificationAnimationController.enableWindowMagnification(scale, centerX,
-                    centerY, callback);
+        final WindowMagnificationController windowMagnificationController =
+                mMagnificationControllerSupplier.get(displayId);
+        if (windowMagnificationController != null) {
+            windowMagnificationController.enableWindowMagnification(scale, centerX, centerY,
+                    magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY, callback);
         }
     }
 
     @MainThread
     void setScale(int displayId, float scale) {
-        final WindowMagnificationAnimationController windowMagnificationAnimationController =
-                mAnimationControllerSupplier.get(displayId);
-        if (windowMagnificationAnimationController != null) {
-            windowMagnificationAnimationController.setScale(scale);
+        final WindowMagnificationController windowMagnificationController =
+                mMagnificationControllerSupplier.get(displayId);
+        if (windowMagnificationController != null) {
+            windowMagnificationController.setScale(scale);
         }
     }
 
     @MainThread
     void moveWindowMagnifier(int displayId, float offsetX, float offsetY) {
-        final WindowMagnificationAnimationController windowMagnificationAnimationController =
-                mAnimationControllerSupplier.get(displayId);
-        if (windowMagnificationAnimationController != null) {
-            windowMagnificationAnimationController.moveWindowMagnifier(offsetX, offsetY);
+        final WindowMagnificationController windowMagnificationcontroller =
+                mMagnificationControllerSupplier.get(displayId);
+        if (windowMagnificationcontroller != null) {
+            windowMagnificationcontroller.moveWindowMagnifier(offsetX, offsetY);
         }
     }
 
     @MainThread
     void disableWindowMagnification(int displayId,
             @Nullable IRemoteMagnificationAnimationCallback callback) {
-        final WindowMagnificationAnimationController windowMagnificationAnimationController =
-                mAnimationControllerSupplier.get(displayId);
-        if (windowMagnificationAnimationController != null) {
-            windowMagnificationAnimationController.deleteWindowMagnification(callback);
+        final WindowMagnificationController windowMagnificationController =
+                mMagnificationControllerSupplier.get(displayId);
+        if (windowMagnificationController != null) {
+            windowMagnificationController.deleteWindowMagnification(callback);
         }
     }
 
@@ -234,8 +236,8 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println(TAG);
-        mAnimationControllerSupplier.forEach(
-                animationController -> animationController.dump(pw));
+        mMagnificationControllerSupplier.forEach(
+                magnificationController -> magnificationController.dump(pw));
     }
 
     private void setWindowMagnificationConnection() {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
index 8cb608f..dc1e005 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationAnimationController.java
@@ -19,6 +19,7 @@
 import android.animation.Animator;
 import android.animation.ValueAnimator;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UiContext;
 import android.content.Context;
@@ -31,7 +32,6 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.R;
 
-import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -54,14 +54,16 @@
     // The window magnification is enabled.
     private static final int STATE_ENABLED = 1;
     // The window magnification is going to be disabled when the animation is end.
-    private  static final int STATE_DISABLING = 2;
+    private static final int STATE_DISABLING = 2;
     // The animation is running for enabling the window magnification.
     private static final int STATE_ENABLING = 3;
 
-    private final WindowMagnificationController mController;
+    private WindowMagnificationController mController;
     private final ValueAnimator mValueAnimator;
     private final AnimationSpec mStartSpec = new AnimationSpec();
     private final AnimationSpec mEndSpec = new AnimationSpec();
+    private float mMagnificationFrameOffsetRatioX = 0f;
+    private float mMagnificationFrameOffsetRatioY = 0f;
     private final Context mContext;
     // Called when the animation is ended successfully without cancelling or mStartSpec and
     // mEndSpec are equal.
@@ -71,23 +73,25 @@
     @MagnificationState
     private int mState = STATE_DISABLED;
 
-    WindowMagnificationAnimationController(@UiContext Context context,
-            WindowMagnificationController controller) {
-        this(context, controller, newValueAnimator(context.getResources()));
+    WindowMagnificationAnimationController(@UiContext Context context) {
+        this(context, newValueAnimator(context.getResources()));
     }
 
     @VisibleForTesting
-    WindowMagnificationAnimationController(Context context,
-            WindowMagnificationController controller, ValueAnimator valueAnimator) {
+    WindowMagnificationAnimationController(Context context, ValueAnimator valueAnimator) {
         mContext = context;
-        mController = controller;
         mValueAnimator = valueAnimator;
         mValueAnimator.addUpdateListener(this);
         mValueAnimator.addListener(this);
     }
 
+    void setWindowMagnificationController(@NonNull WindowMagnificationController controller) {
+        mController = controller;
+    }
+
     /**
-     * Wraps {@link WindowMagnificationController#enableWindowMagnification(float, float, float)}
+     * Wraps {@link WindowMagnificationController#enableWindowMagnification(float, float, float,
+     * float, float, IRemoteMagnificationAnimationCallback)}
      * with transition animation. If the window magnification is not enabled, the scale will start
      * from 1.0 and the center won't be changed during the animation. If {@link #mState} is
      * {@code STATE_DISABLING}, the animation runs in reverse.
@@ -105,13 +109,48 @@
      */
     void enableWindowMagnification(float scale, float centerX, float centerY,
             @Nullable IRemoteMagnificationAnimationCallback animationCallback) {
+        enableWindowMagnification(scale, centerX, centerY, 0f, 0f, animationCallback);
+    }
+
+    /**
+     * Wraps {@link WindowMagnificationController#enableWindowMagnification(float, float, float,
+     * float, float, IRemoteMagnificationAnimationCallback)}
+     * with transition animation. If the window magnification is not enabled, the scale will start
+     * from 1.0 and the center won't be changed during the animation. If {@link #mState} is
+     * {@code STATE_DISABLING}, the animation runs in reverse.
+     *
+     * @param scale   The target scale, or {@link Float#NaN} to leave unchanged.
+     * @param centerX The screen-relative X coordinate around which to center for magnification,
+     *                or {@link Float#NaN} to leave unchanged.
+     * @param centerY The screen-relative Y coordinate around which to center for magnification,
+     *                or {@link Float#NaN} to leave unchanged.
+     * @param magnificationFrameOffsetRatioX Indicate the X coordinate offset between
+     *                                       frame position X and centerX
+     * @param magnificationFrameOffsetRatioY Indicate the Y coordinate offset between
+     *                                       frame position Y and centerY
+     * @param animationCallback Called when the transition is complete, the given arguments
+     *                          are as same as current values, or the transition is interrupted
+     *                          due to the new transition request.
+     *
+     * @see #onAnimationUpdate(ValueAnimator)
+     */
+    void enableWindowMagnification(float scale, float centerX, float centerY,
+            float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
+            @Nullable IRemoteMagnificationAnimationCallback animationCallback) {
+        if (mController == null) {
+            return;
+        }
         sendAnimationCallback(false);
+        mMagnificationFrameOffsetRatioX = magnificationFrameOffsetRatioX;
+        mMagnificationFrameOffsetRatioY = magnificationFrameOffsetRatioY;
+
         // Enable window magnification without animation immediately.
         if (animationCallback == null) {
             if (mState == STATE_ENABLING || mState == STATE_DISABLING) {
                 mValueAnimator.cancel();
             }
-            mController.enableWindowMagnification(scale, centerX, centerY);
+            mController.enableWindowMagnificationInternal(scale, centerX, centerY,
+                    mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
             setState(STATE_ENABLED);
             return;
         }
@@ -119,7 +158,8 @@
         setupEnableAnimationSpecs(scale, centerX, centerY);
         if (mEndSpec.equals(mStartSpec)) {
             if (mState == STATE_DISABLED) {
-                mController.enableWindowMagnification(scale, centerX, centerY);
+                mController.enableWindowMagnificationInternal(scale, centerX, centerY,
+                        mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
             } else if (mState == STATE_ENABLING || mState == STATE_DISABLING) {
                 mValueAnimator.cancel();
             }
@@ -139,6 +179,9 @@
     }
 
     private void setupEnableAnimationSpecs(float scale, float centerX, float centerY) {
+        if (mController == null) {
+            return;
+        }
         final float currentScale = mController.getScale();
         final float currentCenterX = mController.getCenterX();
         final float currentCenterY = mController.getCenterY();
@@ -160,15 +203,9 @@
         }
     }
 
-    /**
-     * Wraps {@link WindowMagnificationController#setScale(float)}. If the animation is
-     * running, it has no effect.
-     */
-    void setScale(float scale) {
-        if (mValueAnimator.isRunning()) {
-            return;
-        }
-        mController.setScale(scale);
+    /** Returns {@code true} if the animator is running. */
+    boolean isAnimating() {
+        return mValueAnimator.isRunning();
     }
 
     /**
@@ -181,6 +218,9 @@
      */
     void deleteWindowMagnification(
             @Nullable IRemoteMagnificationAnimationCallback animationCallback) {
+        if (mController == null) {
+            return;
+        }
         sendAnimationCallback(false);
         // Delete window magnification without animation.
         if (animationCallback == null) {
@@ -206,25 +246,6 @@
         setState(STATE_DISABLING);
     }
 
-    /**
-     * Wraps {@link WindowMagnificationController#moveWindowMagnifier(float, float)}. If the
-     * animation is running, it has no effect.
-     * @param offsetX The amount in pixels to offset the window magnifier in the X direction, in
-     *                current screen pixels.
-     * @param offsetY The amount in pixels to offset the window magnifier in the Y direction, in
-     *                current screen pixels.
-     */
-    void moveWindowMagnifier(float offsetX, float offsetY) {
-        if (mValueAnimator.isRunning()) {
-            return;
-        }
-        mController.moveWindowMagnifier(offsetX, offsetY);
-    }
-
-    void onConfigurationChanged(int configDiff) {
-        mController.onConfigurationChanged(configDiff);
-    }
-
     private void setState(@MagnificationState int state) {
         if (DEBUG) {
             Log.d(TAG, "setState from " + mState + " to " + state);
@@ -239,7 +260,7 @@
 
     @Override
     public void onAnimationEnd(Animator animation, boolean isReverse) {
-        if (mEndAnimationCanceled) {
+        if (mEndAnimationCanceled || mController == null) {
             return;
         }
         if (Float.isNaN(mController.getScale())) {
@@ -279,21 +300,17 @@
 
     @Override
     public void onAnimationUpdate(ValueAnimator animation) {
+        if (mController == null) {
+            return;
+        }
         final float fract = animation.getAnimatedFraction();
         final float sentScale = mStartSpec.mScale + (mEndSpec.mScale - mStartSpec.mScale) * fract;
         final float centerX =
                 mStartSpec.mCenterX + (mEndSpec.mCenterX - mStartSpec.mCenterX) * fract;
         final float centerY =
                 mStartSpec.mCenterY + (mEndSpec.mCenterY - mStartSpec.mCenterY) * fract;
-        mController.enableWindowMagnification(sentScale, centerX, centerY);
-    }
-
-    public void updateSysUiStateFlag() {
-        mController.updateSysUIStateFlag();
-    }
-
-    void dump(PrintWriter pw) {
-        mController.dump(pw);
+        mController.enableWindowMagnificationInternal(sentScale, centerX, centerY,
+                mMagnificationFrameOffsetRatioX, mMagnificationFrameOffsetRatioY);
     }
 
     private static ValueAnimator newValueAnimator(Resources resources) {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java
index 92cd8b1..2133da2 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationConnectionImpl.java
@@ -49,11 +49,13 @@
     }
 
     @Override
-    public void enableWindowMagnification(int displayId, float scale, float centerX,
-            float centerY, IRemoteMagnificationAnimationCallback callback) {
+    public void enableWindowMagnification(int displayId, float scale, float centerX, float centerY,
+            float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
+            IRemoteMagnificationAnimationCallback callback) {
         mHandler.post(
                 () -> mWindowMagnification.enableWindowMagnification(displayId, scale, centerX,
-                        centerY, callback));
+                        centerY, magnificationFrameOffsetRatioX,
+                        magnificationFrameOffsetRatioY, callback));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index b48def2..b064ba9 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -59,6 +59,7 @@
 import android.view.WindowMetrics;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
+import android.view.accessibility.IRemoteMagnificationAnimationCallback;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
@@ -94,17 +95,46 @@
     @Surface.Rotation
     @VisibleForTesting
     int mRotation;
-    private final Rect mMagnificationFrame = new Rect();
     private final SurfaceControl.Transaction mTransaction;
 
     private final WindowManager mWm;
 
     private float mScale;
 
+    /**
+     * MagnificationFrame represents the bound of {@link #mMirrorSurface} and is constrained
+     * by the {@link #mMagnificationFrameBoundary}.
+     * We use MagnificationFrame to calculate the position of {@link #mMirrorView}.
+     * We combine MagnificationFrame with {@link #mMagnificationFrameOffsetX} and
+     * {@link #mMagnificationFrameOffsetY} to calculate the position of {@link #mSourceBounds}.
+     */
+    private final Rect mMagnificationFrame = new Rect();
     private final Rect mTmpRect = new Rect();
+
+    /**
+     * MirrorViewBounds is the bound of the {@link #mMirrorView} which displays the magnified
+     * content.
+     * {@link #mMirrorView}'s center is equal to {@link #mMagnificationFrame}'s center.
+     */
     private final Rect mMirrorViewBounds = new Rect();
+
+    /**
+     * SourceBound is the bound of the magnified region which projects the magnified content.
+     * SourceBound's center is equal to the parameters centerX and centerY in
+     * {@link WindowMagnificationController#enableWindowMagnificationInternal(float, float, float)}}
+     * but it is calculated from {@link #mMagnificationFrame}'s center in the runtime.
+     */
     private final Rect mSourceBounds = new Rect();
 
+    /**
+     * The relation of centers between {@link #mSourceBounds} and {@link #mMagnificationFrame} is
+     * calculated in {@link #calculateSourceBounds(Rect, float)} and the equations are as following:
+     *      MagnificationFrame = SourceBound (e.g., centerX & centerY) + MagnificationFrameOffset
+     *      SourceBound = MagnificationFrame - MagnificationFrameOffset
+     */
+    private int mMagnificationFrameOffsetX = 0;
+    private int mMagnificationFrameOffsetY = 0;
+
     // The root of the mirrored content
     private SurfaceControl mMirrorSurface;
 
@@ -122,6 +152,7 @@
     private final Runnable mMirrorViewRunnable;
     private final Runnable mUpdateStateDescriptionRunnable;
     private final Runnable mWindowInsetChangeRunnable;
+    // MirrorView is the mirror window which displays the magnified content.
     private View mMirrorView;
     private SurfaceView mMirrorSurfaceView;
     private int mMirrorSurfaceMargin;
@@ -133,6 +164,7 @@
     // The top Y of the system gesture rect at the bottom. Set to -1 if it is invalid.
     private int mSystemGestureTop = -1;
 
+    private final WindowMagnificationAnimationController mAnimationController;
     private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
     private final MagnificationGestureDetector mGestureDetector;
     private final int mBounceEffectDuration;
@@ -148,11 +180,14 @@
     private MirrorWindowControl mMirrorWindowControl;
 
     WindowMagnificationController(@UiContext Context context, @NonNull Handler handler,
+            @NonNull WindowMagnificationAnimationController animationController,
             SfVsyncFrameCallbackProvider sfVsyncFrameProvider,
             MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction,
             @NonNull WindowMagnifierCallback callback, SysUiState sysUiState) {
         mContext = context;
         mHandler = handler;
+        mAnimationController = animationController;
+        mAnimationController.setWindowMagnificationController(this);
         mSfVsyncFrameProvider = sfVsyncFrameProvider;
         mWindowMagnifierCallback = callback;
         mSysUiState = sysUiState;
@@ -259,6 +294,19 @@
     }
 
     /**
+     * Wraps {@link WindowMagnificationController#deleteWindowMagnification()}} with transition
+     * animation. If the window magnification is enabling, it runs the animation in reverse.
+     *
+     * @param animationCallback Called when the transition is complete, the given arguments
+     *                          are as same as current values, or the transition is interrupted
+     *                          due to the new transition request.
+     */
+    void deleteWindowMagnification(
+            @Nullable IRemoteMagnificationAnimationCallback animationCallback) {
+        mAnimationController.deleteWindowMagnification(animationCallback);
+    }
+
+    /**
      * Deletes the magnification window.
      */
     void deleteWindowMagnification() {
@@ -321,7 +369,7 @@
         // window size changed not caused by rotation.
         if (isWindowVisible() && reCreateWindow) {
             deleteWindowMagnification();
-            enableWindowMagnification(Float.NaN, Float.NaN, Float.NaN);
+            enableWindowMagnificationInternal(Float.NaN, Float.NaN, Float.NaN);
         }
     }
 
@@ -615,6 +663,26 @@
         int top = displayFrame.top + (halfHeight - (int) (halfHeight / scale));
         int bottom = displayFrame.bottom - (halfHeight - (int) (halfHeight / scale));
         mSourceBounds.set(left, top, right, bottom);
+
+        // SourceBound's center is equal to center[X,Y] but calculated from MagnificationFrame's
+        // center. The relation between SourceBound and MagnificationFrame is as following:
+        //          MagnificationFrame = SourceBound (center[X,Y]) + MagnificationFrameOffset
+        //          SourceBound = MagnificationFrame - MagnificationFrameOffset
+        mSourceBounds.offset(-mMagnificationFrameOffsetX, -mMagnificationFrameOffsetY);
+
+        if (mSourceBounds.left < 0) {
+            mSourceBounds.offsetTo(0, mSourceBounds.top);
+        } else if (mSourceBounds.right > mWindowBounds.width()) {
+            mSourceBounds.offsetTo(mWindowBounds.width() - mSourceBounds.width(),
+                    mSourceBounds.top);
+        }
+
+        if (mSourceBounds.top < 0) {
+            mSourceBounds.offsetTo(mSourceBounds.left, 0);
+        } else if (mSourceBounds.bottom > mWindowBounds.height()) {
+            mSourceBounds.offsetTo(mSourceBounds.left,
+                    mWindowBounds.height() - mSourceBounds.height());
+        }
     }
 
     private void calculateMagnificationFrameBoundary() {
@@ -628,11 +696,31 @@
         final int scaledWidth = (int) (halfWidth / mScale);
         // The scaled half height of magnified region.
         final int scaledHeight = (int) (halfHeight / mScale);
-        final int exceededWidth = halfWidth - scaledWidth;
-        final int exceededHeight = halfHeight - scaledHeight;
 
-        mMagnificationFrameBoundary.set(-exceededWidth, -exceededHeight,
-                mWindowBounds.width() + exceededWidth, mWindowBounds.height() + exceededHeight);
+        // MagnificationFrameBoundary constrain the space of MagnificationFrame, and it also has
+        // to leave enough space for SourceBound to magnify the whole screen space.
+        // However, there is an offset between SourceBound and MagnificationFrame.
+        // The relation between SourceBound and MagnificationFrame is as following:
+        //      SourceBound = MagnificationFrame - MagnificationFrameOffset
+        // Therefore, we have to adjust the exceededBoundary based on the offset.
+        //
+        // We have to increase the offset space for the SourceBound edges which are located in
+        // the MagnificationFrame. For example, if the offsetX and offsetY are negative, which
+        // means SourceBound is at right-bottom size of MagnificationFrame, the left and top
+        // edges of SourceBound are located in MagnificationFrame. So, we have to leave extra
+        // offset space at left and top sides and don't have to leave extra space at right and
+        // bottom sides.
+        final int exceededLeft = Math.max(halfWidth - scaledWidth - mMagnificationFrameOffsetX, 0);
+        final int exceededRight = Math.max(halfWidth - scaledWidth + mMagnificationFrameOffsetX, 0);
+        final int exceededTop = Math.max(halfHeight - scaledHeight - mMagnificationFrameOffsetY, 0);
+        final int exceededBottom = Math.max(halfHeight - scaledHeight + mMagnificationFrameOffsetY,
+                0);
+
+        mMagnificationFrameBoundary.set(
+                -exceededLeft,
+                -exceededTop,
+                mWindowBounds.width() + exceededRight,
+                mWindowBounds.height() + exceededBottom);
     }
 
     /**
@@ -693,27 +781,89 @@
     }
 
     /**
+     * Wraps {@link WindowMagnificationController#enableWindowMagnificationInternal(float, float,
+     * float, float, float)}
+     * with transition animation. If the window magnification is not enabled, the scale will start
+     * from 1.0 and the center won't be changed during the animation. If animator is
+     * {@code STATE_DISABLING}, the animation runs in reverse.
+     *
+     * @param scale   The target scale, or {@link Float#NaN} to leave unchanged.
+     * @param centerX The screen-relative X coordinate around which to center for magnification,
+     *                or {@link Float#NaN} to leave unchanged.
+     * @param centerY The screen-relative Y coordinate around which to center for magnification,
+     *                or {@link Float#NaN} to leave unchanged.
+     * @param magnificationFrameOffsetRatioX Indicate the X coordinate offset
+     *                                       between frame position X and centerX
+     * @param magnificationFrameOffsetRatioY Indicate the Y coordinate offset
+     *                                       between frame position Y and centerY
+     * @param animationCallback Called when the transition is complete, the given arguments
+     *                          are as same as current values, or the transition is interrupted
+     *                          due to the new transition request.
+     */
+    void enableWindowMagnification(float scale, float centerX, float centerY,
+            float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
+            @Nullable IRemoteMagnificationAnimationCallback animationCallback) {
+        mAnimationController.enableWindowMagnification(scale, centerX, centerY,
+                magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY, animationCallback);
+    }
+
+    /**
      * Enables window magnification with specified parameters. If the given scale is <strong>less
      * than or equal to 1.0f<strong>, then
      * {@link WindowMagnificationController#deleteWindowMagnification()} will be called instead to
      * be consistent with the behavior of display magnification.
      *
      * @param scale   the target scale, or {@link Float#NaN} to leave unchanged
-     * @param centerX the screen-relative X coordinate around which to center,
+     * @param centerX the screen-relative X coordinate around which to center for magnification,
      *                or {@link Float#NaN} to leave unchanged.
-     * @param centerY the screen-relative Y coordinate around which to center,
+     * @param centerY the screen-relative Y coordinate around which to center for magnification,
      *                or {@link Float#NaN} to leave unchanged.
      */
-    void enableWindowMagnification(float scale, float centerX, float centerY) {
+    void enableWindowMagnificationInternal(float scale, float centerX, float centerY) {
+        enableWindowMagnificationInternal(scale, centerX, centerY, Float.NaN, Float.NaN);
+    }
+
+    /**
+     * Enables window magnification with specified parameters. If the given scale is <strong>less
+     * than or equal to 1.0f<strong>, then
+     * {@link WindowMagnificationController#deleteWindowMagnification()} will be called instead to
+     * be consistent with the behavior of display magnification.
+     *
+     * @param scale   the target scale, or {@link Float#NaN} to leave unchanged
+     * @param centerX the screen-relative X coordinate around which to center for magnification,
+     *                or {@link Float#NaN} to leave unchanged.
+     * @param centerY the screen-relative Y coordinate around which to center for magnification,
+     *                or {@link Float#NaN} to leave unchanged.
+     * @param magnificationFrameOffsetRatioX Indicate the X coordinate offset
+     *                                       between frame position X and centerX,
+     *                                       or {@link Float#NaN} to leave unchanged.
+     * @param magnificationFrameOffsetRatioY Indicate the Y coordinate offset
+     *                                       between frame position Y and centerY,
+     *                                       or {@link Float#NaN} to leave unchanged.
+     */
+    void enableWindowMagnificationInternal(float scale, float centerX, float centerY,
+            float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY) {
         if (Float.compare(scale, 1.0f)  <= 0) {
             deleteWindowMagnification();
             return;
         }
 
+        mMagnificationFrameOffsetX = Float.isNaN(magnificationFrameOffsetRatioX)
+                ? mMagnificationFrameOffsetX
+                : (int) (mMagnificationFrame.width() / 2 * magnificationFrameOffsetRatioX);
+        mMagnificationFrameOffsetY = Float.isNaN(magnificationFrameOffsetRatioY)
+                ? mMagnificationFrameOffsetY
+                : (int) (mMagnificationFrame.height() / 2 * magnificationFrameOffsetRatioY);
+
+        // The relation of centers between SourceBound and MagnificationFrame is as following:
+        // MagnificationFrame = SourceBound (e.g., centerX & centerY) + MagnificationFrameOffset
+        final float newMagnificationFrameCenterX = centerX + mMagnificationFrameOffsetX;
+        final float newMagnificationFrameCenterY = centerY + mMagnificationFrameOffsetY;
+
         final float offsetX = Float.isNaN(centerX) ? 0
-                : centerX - mMagnificationFrame.exactCenterX();
+                : newMagnificationFrameCenterX - mMagnificationFrame.exactCenterX();
         final float offsetY = Float.isNaN(centerY) ? 0
-                : centerY - mMagnificationFrame.exactCenterY();
+                : newMagnificationFrameCenterY - mMagnificationFrame.exactCenterY();
         mScale = Float.isNaN(scale) ? mScale : scale;
 
         calculateMagnificationFrameBoundary();
@@ -732,10 +882,10 @@
      * @param scale the target scale, or {@link Float#NaN} to leave unchanged
      */
     void setScale(float scale) {
-        if (!isWindowVisible() || mScale == scale) {
+        if (mAnimationController.isAnimating() || !isWindowVisible() || mScale == scale) {
             return;
         }
-        enableWindowMagnification(scale, Float.NaN, Float.NaN);
+        enableWindowMagnificationInternal(scale, Float.NaN, Float.NaN);
         mHandler.removeCallbacks(mUpdateStateDescriptionRunnable);
         mHandler.postDelayed(mUpdateStateDescriptionRunnable, UPDATE_STATE_DESCRIPTION_DELAY_MS);
     }
@@ -749,7 +899,7 @@
      *                current screen pixels.
      */
     void moveWindowMagnifier(float offsetX, float offsetY) {
-        if (mMirrorSurfaceView == null) {
+        if (mAnimationController.isAnimating() || mMirrorSurfaceView == null) {
             return;
         }
         if (updateMagnificationFramePosition((int) offsetX, (int) offsetY)) {
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
index cff6cf1..cc5a792 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuController.java
@@ -98,7 +98,8 @@
         mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
 
-        init();
+        mIsKeyguardVisible = false;
+        mIsAccessibilityManagerServiceReady = false;
     }
 
     /**
@@ -124,9 +125,8 @@
         handleFloatingMenuVisibility(mIsKeyguardVisible, mBtnMode, mBtnTargets);
     }
 
-    private void init() {
-        mIsKeyguardVisible = false;
-        mIsAccessibilityManagerServiceReady = false;
+    /** Initializes the AccessibilityFloatingMenuController configurations. */
+    public void init() {
         mBtnMode = mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode();
         mBtnTargets = mAccessibilityButtonTargetsObserver.getCurrentAccessibilityButtonTargets();
         registerContentObservers();
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index b1197e6..9d5b93c 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -7,7 +7,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.SearchManager;
 import android.content.ActivityNotFoundException;
@@ -27,17 +26,16 @@
 
 import com.android.internal.app.AssistUtils;
 import com.android.internal.app.IVoiceInteractionSessionListener;
-import com.android.internal.app.IVoiceInteractionSessionShowCallback;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.R;
 import com.android.systemui.assist.ui.DefaultUiController;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 
 import javax.inject.Inject;
@@ -124,23 +122,8 @@
 
     private final DeviceProvisionedController mDeviceProvisionedController;
     private final CommandQueue mCommandQueue;
-    private final AssistOrbController mOrbController;
     protected final AssistUtils mAssistUtils;
 
-    private IVoiceInteractionSessionShowCallback mShowCallback =
-            new IVoiceInteractionSessionShowCallback.Stub() {
-
-                @Override
-                public void onFailed() throws RemoteException {
-                    mOrbController.postHide();
-                }
-
-                @Override
-                public void onShown() throws RemoteException {
-                    mOrbController.postHide();
-                }
-            };
-
     @Inject
     public AssistManager(
             DeviceProvisionedController controller,
@@ -149,20 +132,18 @@
             CommandQueue commandQueue,
             PhoneStateMonitor phoneStateMonitor,
             OverviewProxyService overviewProxyService,
-            ConfigurationController configurationController,
             Lazy<SysUiState> sysUiState,
             DefaultUiController defaultUiController,
-            AssistLogger assistLogger) {
+            AssistLogger assistLogger,
+            @Main Handler uiHandler) {
         mContext = context;
         mDeviceProvisionedController = controller;
         mCommandQueue = commandQueue;
         mAssistUtils = assistUtils;
-        mAssistDisclosure = new AssistDisclosure(context, new Handler());
+        mAssistDisclosure = new AssistDisclosure(context, uiHandler);
         mPhoneStateMonitor = phoneStateMonitor;
         mAssistLogger = assistLogger;
 
-        mOrbController = new AssistOrbController(configurationController, context);
-
         registerVoiceInteractionSessionListener();
 
         mUiController = defaultUiController;
@@ -223,10 +204,6 @@
                 });
     }
 
-    protected boolean shouldShowOrb() {
-        return !ActivityManager.isLowRamDeviceStatic();
-    }
-
     public void startAssist(Bundle args) {
         final ComponentName assistComponent = getAssistInfo();
         if (assistComponent == null) {
@@ -234,10 +211,6 @@
         }
 
         final boolean isService = assistComponent.equals(getVoiceInteractorComponentName());
-        if (!isService || (!isVoiceSessionRunning() && shouldShowOrb())) {
-            mOrbController.showOrb(assistComponent, isService);
-            mOrbController.postHideDelayed(isService ? TIMEOUT_SERVICE : TIMEOUT_ACTIVITY);
-        }
 
         if (args == null) {
             args = new Bundle();
@@ -329,7 +302,7 @@
 
     private void startVoiceInteractor(Bundle args) {
         mAssistUtils.showSessionForActiveService(args,
-                VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, mShowCallback, null);
+                VoiceInteractionSession.SHOW_SOURCE_ASSIST_GESTURE, null, null);
     }
 
     public void launchVoiceAssistFromKeyguard() {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java
deleted file mode 100644
index 95b9e81..0000000
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbContainer.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2015 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.assist;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.FrameLayout;
-
-import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
-
-public class AssistOrbContainer extends FrameLayout {
-
-    private static final long EXIT_START_DELAY = 150;
-
-    private View mScrim;
-    private View mNavbarScrim;
-    private AssistOrbView mOrb;
-
-    private boolean mAnimatingOut;
-
-    public AssistOrbContainer(Context context) {
-        this(context, null);
-    }
-
-    public AssistOrbContainer(Context context, @Nullable AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public AssistOrbContainer(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mScrim = findViewById(R.id.assist_orb_scrim);
-        mNavbarScrim = findViewById(R.id.assist_orb_navbar_scrim);
-        mOrb = (AssistOrbView) findViewById(R.id.assist_orb);
-    }
-
-    public void show(final boolean show, boolean animate, Runnable onDone) {
-        if (show) {
-            if (getVisibility() != View.VISIBLE) {
-                setVisibility(View.VISIBLE);
-                if (animate) {
-                    startEnterAnimation(onDone);
-                } else {
-                    reset();
-                    if (onDone != null) {
-                        onDone.run();
-                    }
-                }
-            }
-        } else {
-            if (animate) {
-                startExitAnimation(new Runnable() {
-                    @Override
-                    public void run() {
-                        mAnimatingOut = false;
-                        setVisibility(View.GONE);
-                        if (onDone != null) {
-                            onDone.run();
-                        }
-                    }
-                });
-            } else {
-                setVisibility(View.GONE);
-                if (onDone != null) {
-                    onDone.run();
-                }
-            }
-        }
-    }
-
-    private void reset() {
-        mAnimatingOut = false;
-        mOrb.reset();
-        mScrim.setAlpha(1f);
-        mNavbarScrim.setAlpha(1f);
-    }
-
-    private void startEnterAnimation(Runnable onDone) {
-        if (mAnimatingOut) {
-            return;
-        }
-        mOrb.startEnterAnimation();
-        mScrim.setAlpha(0f);
-        mNavbarScrim.setAlpha(0f);
-        post(new Runnable() {
-            @Override
-            public void run() {
-                mScrim.animate()
-                        .alpha(1f)
-                        .setDuration(300)
-                        .setStartDelay(0)
-                        .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-                mNavbarScrim.animate()
-                        .alpha(1f)
-                        .setDuration(300)
-                        .setStartDelay(0)
-                        .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
-                        .withEndAction(onDone);
-            }
-        });
-    }
-
-    private void startExitAnimation(final Runnable endRunnable) {
-        if (mAnimatingOut) {
-            if (endRunnable != null) {
-                endRunnable.run();
-            }
-            return;
-        }
-        mAnimatingOut = true;
-        mOrb.startExitAnimation(EXIT_START_DELAY);
-        mScrim.animate()
-                .alpha(0f)
-                .setDuration(250)
-                .setStartDelay(EXIT_START_DELAY)
-                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
-        mNavbarScrim.animate()
-                .alpha(0f)
-                .setDuration(250)
-                .setStartDelay(EXIT_START_DELAY)
-                .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
-                .withEndAction(endRunnable);
-    }
-
-    /**
-     * Whether the panel is showing, or, if it's animating, whether it will be
-     * when the animation is done.
-     */
-    public boolean isShowing() {
-        return getVisibility() == View.VISIBLE && !mAnimatingOut;
-    }
-
-    public AssistOrbView getOrb() {
-        return mOrb;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java
deleted file mode 100644
index 4082015..0000000
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbController.java
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2021 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.assist;
-
-import android.annotation.NonNull;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.PixelFormat;
-import android.os.Binder;
-import android.os.Bundle;
-import android.util.Log;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.ImageView;
-
-import com.android.settingslib.applications.InterestingConfigChanges;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-
-/**
- * AssistOrbController controls the showing and hiding of the assistant orb.
- */
-public class AssistOrbController {
-    private static final String ASSIST_ICON_METADATA_NAME =
-            "com.android.systemui.action_assist_icon";
-    private static final String TAG = "AssistOrbController";
-    private static final boolean VERBOSE = false;
-
-    private final InterestingConfigChanges mInterestingConfigChanges;
-    private AssistOrbContainer mView;
-    private final Context mContext;
-    private final WindowManager mWindowManager;
-
-    private Runnable mHideRunnable = new Runnable() {
-        @Override
-        public void run() {
-            mView.removeCallbacks(this);
-            mView.show(false /* show */, true /* animate */, () -> {
-                if (mView.isAttachedToWindow()) {
-                    mWindowManager.removeView(mView);
-                }
-            });
-        }
-    };
-
-    private ConfigurationController.ConfigurationListener mConfigurationListener =
-            new ConfigurationController.ConfigurationListener() {
-                @Override
-                public void onConfigChanged(Configuration newConfig) {
-                    if (!mInterestingConfigChanges.applyNewConfig(mContext.getResources())) {
-                        return;
-                    }
-                    boolean visible = false;
-                    if (mView != null) {
-                        visible = mView.isShowing();
-                        if (mView.isAttachedToWindow()) {
-                            mWindowManager.removeView(mView);
-                        }
-                    }
-
-                    if (visible) {
-                        showOrb(false);
-                    }
-                }
-            };
-
-    AssistOrbController(ConfigurationController configurationController, Context context) {
-        mContext = context;
-        mWindowManager =  mContext.getSystemService(WindowManager.class);
-        mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
-                | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
-                | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
-
-        configurationController.addCallback(mConfigurationListener);
-        mConfigurationListener.onConfigChanged(context.getResources().getConfiguration());
-    }
-
-    public void postHide() {
-        mView.post(mHideRunnable);
-    }
-
-    public void postHideDelayed(long delayMs) {
-        mView.postDelayed(mHideRunnable, delayMs);
-    }
-
-    private void showOrb(boolean animated) {
-        if (mView == null) {
-            mView = (AssistOrbContainer) LayoutInflater.from(mContext).inflate(
-                    R.layout.assist_orb, null);
-            mView.setVisibility(View.GONE);
-            mView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                    | View.SYSTEM_UI_FLAG_LAYOUT_STABLE
-                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
-        }
-        if (!mView.isAttachedToWindow()) {
-            WindowManager.LayoutParams params = getLayoutParams();
-            mWindowManager.addView(mView, params);
-        }
-        mView.show(true, animated, null);
-    }
-
-    private WindowManager.LayoutParams getLayoutParams() {
-        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                mContext.getResources().getDimensionPixelSize(R.dimen.assist_orb_scrim_height),
-                WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING,
-                WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                        | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
-                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
-                PixelFormat.TRANSLUCENT);
-        lp.token = new Binder();
-        lp.gravity = Gravity.BOTTOM | Gravity.START;
-        lp.setTitle("AssistPreviewPanel");
-        lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED
-                | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
-        return lp;
-    }
-
-    public void showOrb(@NonNull ComponentName assistComponent, boolean isService) {
-        showOrb(true);
-        maybeSwapSearchIcon(assistComponent, isService);
-    }
-
-    private void maybeSwapSearchIcon(@NonNull ComponentName assistComponent, boolean isService) {
-        replaceDrawable(mView.getOrb().getLogo(), assistComponent, ASSIST_ICON_METADATA_NAME,
-                isService);
-    }
-
-    public void replaceDrawable(ImageView v, ComponentName component, String name,
-            boolean isService) {
-        if (component != null) {
-            try {
-                PackageManager packageManager = mContext.getPackageManager();
-                // Look for the search icon specified in the activity meta-data
-                Bundle metaData = isService
-                        ? packageManager.getServiceInfo(
-                        component, PackageManager.GET_META_DATA).metaData
-                        : packageManager.getActivityInfo(
-                                component, PackageManager.GET_META_DATA).metaData;
-                if (metaData != null) {
-                    int iconResId = metaData.getInt(name);
-                    if (iconResId != 0) {
-                        Resources res = packageManager.getResourcesForApplication(
-                                component.getPackageName());
-                        v.setImageDrawable(res.getDrawable(iconResId));
-                        return;
-                    }
-                }
-            } catch (PackageManager.NameNotFoundException e) {
-                if (VERBOSE) {
-                    Log.v(TAG, "Assistant component "
-                            + component.flattenToShortString() + " not found");
-                }
-            } catch (Resources.NotFoundException nfe) {
-                Log.w(TAG, "Failed to swap drawable from "
-                        + component.flattenToShortString(), nfe);
-            }
-        }
-        v.setImageDrawable(null);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java b/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
deleted file mode 100644
index 16d9c84..0000000
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistOrbView.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2014 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.assist;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Outline;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewOutlineProvider;
-import android.view.animation.Interpolator;
-import android.view.animation.OvershootInterpolator;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-import com.android.systemui.R;
-import com.android.systemui.animation.Interpolators;
-
-public class AssistOrbView extends FrameLayout {
-
-    private final int mCircleMinSize;
-    private final int mBaseMargin;
-    private final int mStaticOffset;
-    private final Paint mBackgroundPaint = new Paint();
-    private final Rect mCircleRect = new Rect();
-    private final Rect mStaticRect = new Rect();
-    private final Interpolator mOvershootInterpolator = new OvershootInterpolator();
-
-    private boolean mClipToOutline;
-    private final int mMaxElevation;
-    private float mOutlineAlpha;
-    private float mOffset;
-    private float mCircleSize;
-    private ImageView mLogo;
-    private float mCircleAnimationEndValue;
-
-    private ValueAnimator mOffsetAnimator;
-    private ValueAnimator mCircleAnimator;
-
-    private ValueAnimator.AnimatorUpdateListener mCircleUpdateListener
-            = new ValueAnimator.AnimatorUpdateListener() {
-        @Override
-        public void onAnimationUpdate(ValueAnimator animation) {
-            applyCircleSize((float) animation.getAnimatedValue());
-            updateElevation();
-        }
-    };
-    private AnimatorListenerAdapter mClearAnimatorListener = new AnimatorListenerAdapter() {
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            mCircleAnimator = null;
-        }
-    };
-    private ValueAnimator.AnimatorUpdateListener mOffsetUpdateListener
-            = new ValueAnimator.AnimatorUpdateListener() {
-        @Override
-        public void onAnimationUpdate(ValueAnimator animation) {
-            mOffset = (float) animation.getAnimatedValue();
-            updateLayout();
-        }
-    };
-
-
-    public AssistOrbView(Context context) {
-        this(context, null);
-    }
-
-    public AssistOrbView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr) {
-        this(context, attrs, defStyleAttr, 0);
-    }
-
-    public AssistOrbView(Context context, AttributeSet attrs, int defStyleAttr,
-            int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-        setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                if (mCircleSize > 0.0f) {
-                    outline.setOval(mCircleRect);
-                } else {
-                    outline.setEmpty();
-                }
-                outline.setAlpha(mOutlineAlpha);
-            }
-        });
-        setWillNotDraw(false);
-        mCircleMinSize = context.getResources().getDimensionPixelSize(
-                R.dimen.assist_orb_size);
-        mBaseMargin = context.getResources().getDimensionPixelSize(
-                R.dimen.assist_orb_base_margin);
-        mStaticOffset = context.getResources().getDimensionPixelSize(
-                R.dimen.assist_orb_travel_distance);
-        mMaxElevation = context.getResources().getDimensionPixelSize(
-                R.dimen.assist_orb_elevation);
-        mBackgroundPaint.setAntiAlias(true);
-        mBackgroundPaint.setColor(getResources().getColor(R.color.assist_orb_color));
-    }
-
-    public ImageView getLogo() {
-        return mLogo;
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        drawBackground(canvas);
-    }
-
-    private void drawBackground(Canvas canvas) {
-        canvas.drawCircle(mCircleRect.centerX(), mCircleRect.centerY(), mCircleSize / 2,
-                mBackgroundPaint);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mLogo = findViewById(R.id.search_logo);
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        mLogo.layout(0, 0, mLogo.getMeasuredWidth(), mLogo.getMeasuredHeight());
-        if (changed) {
-            updateCircleRect(mStaticRect, mStaticOffset, true);
-        }
-    }
-
-    public void animateCircleSize(float circleSize, long duration,
-            long startDelay, Interpolator interpolator) {
-        if (circleSize == mCircleAnimationEndValue) {
-            return;
-        }
-        if (mCircleAnimator != null) {
-            mCircleAnimator.cancel();
-        }
-        mCircleAnimator = ValueAnimator.ofFloat(mCircleSize, circleSize);
-        mCircleAnimator.addUpdateListener(mCircleUpdateListener);
-        mCircleAnimator.addListener(mClearAnimatorListener);
-        mCircleAnimator.setInterpolator(interpolator);
-        mCircleAnimator.setDuration(duration);
-        mCircleAnimator.setStartDelay(startDelay);
-        mCircleAnimator.start();
-        mCircleAnimationEndValue = circleSize;
-    }
-
-    private void applyCircleSize(float circleSize) {
-        mCircleSize = circleSize;
-        updateLayout();
-    }
-
-    private void updateElevation() {
-        float t = (mStaticOffset - mOffset) / (float) mStaticOffset;
-        t = 1.0f - Math.max(t, 0.0f);
-        float offset = t * mMaxElevation;
-        setElevation(offset);
-    }
-
-    /**
-     * Animates the offset to the edge of the screen.
-     *
-     * @param offset The offset to apply.
-     * @param startDelay The desired start delay if animated.
-     *
-     * @param interpolator The desired interpolator if animated. If null,
-     *                     a default interpolator will be taken designed for appearing or
-     *                     disappearing.
-     */
-    private void animateOffset(float offset, long duration, long startDelay,
-            Interpolator interpolator) {
-        if (mOffsetAnimator != null) {
-            mOffsetAnimator.removeAllListeners();
-            mOffsetAnimator.cancel();
-        }
-        mOffsetAnimator = ValueAnimator.ofFloat(mOffset, offset);
-        mOffsetAnimator.addUpdateListener(mOffsetUpdateListener);
-        mOffsetAnimator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mOffsetAnimator = null;
-            }
-        });
-        mOffsetAnimator.setInterpolator(interpolator);
-        mOffsetAnimator.setStartDelay(startDelay);
-        mOffsetAnimator.setDuration(duration);
-        mOffsetAnimator.start();
-    }
-
-    private void updateLayout() {
-        updateCircleRect();
-        updateLogo();
-        invalidateOutline();
-        invalidate();
-        updateClipping();
-    }
-
-    private void updateClipping() {
-        boolean clip = mCircleSize < mCircleMinSize;
-        if (clip != mClipToOutline) {
-            setClipToOutline(clip);
-            mClipToOutline = clip;
-        }
-    }
-
-    private void updateLogo() {
-        float translationX = (mCircleRect.left + mCircleRect.right) / 2.0f - mLogo.getWidth() / 2.0f;
-        float translationY = (mCircleRect.top + mCircleRect.bottom) / 2.0f
-                - mLogo.getHeight() / 2.0f - mCircleMinSize / 7f;
-        float t = (mStaticOffset - mOffset) / (float) mStaticOffset;
-        translationY += t * mStaticOffset * 0.1f;
-        float alpha = 1.0f-t;
-        alpha = Math.max((alpha - 0.5f) * 2.0f, 0);
-        mLogo.setImageAlpha((int) (alpha * 255));
-        mLogo.setTranslationX(translationX);
-        mLogo.setTranslationY(translationY);
-    }
-
-    private void updateCircleRect() {
-        updateCircleRect(mCircleRect, mOffset, false);
-    }
-
-    private void updateCircleRect(Rect rect, float offset, boolean useStaticSize) {
-        int left, top;
-        float circleSize = useStaticSize ? mCircleMinSize : mCircleSize;
-        left = (int) (getWidth() - circleSize) / 2;
-        top = (int) (getHeight() - circleSize / 2 - mBaseMargin - offset);
-        rect.set(left, top, (int) (left + circleSize), (int) (top + circleSize));
-    }
-
-    public void startExitAnimation(long delay) {
-        animateCircleSize(0, 200, delay, Interpolators.FAST_OUT_LINEAR_IN);
-        animateOffset(0, 200, delay, Interpolators.FAST_OUT_LINEAR_IN);
-    }
-
-    public void startEnterAnimation() {
-        applyCircleSize(0);
-        post(new Runnable() {
-            @Override
-            public void run() {
-                animateCircleSize(mCircleMinSize, 300, 0 /* delay */, mOvershootInterpolator);
-                animateOffset(mStaticOffset, 400, 0 /* delay */, Interpolators.LINEAR_OUT_SLOW_IN);
-            }
-        });
-    }
-
-    public void reset() {
-        mClipToOutline = false;
-        mBackgroundPaint.setAlpha(255);
-        mOutlineAlpha = 1.0f;
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        // not really true but it's ok during an animation, as it's never permanent
-        return false;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 1bad19e..3f077f5 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -39,14 +39,15 @@
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.hardware.fingerprint.IUdfpsOverlayController;
 import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
-import android.media.AudioAttributes;
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.Trace;
+import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -163,14 +164,18 @@
     private boolean mAttemptedToDismissKeyguard;
     private Set<Callback> mCallbacks = new HashSet<>();
 
+    // by default, use low tick
+    private int mPrimitiveTick = VibrationEffect.Composition.PRIMITIVE_LOW_TICK;
+    private final VibrationEffect mTick;
+
     @VisibleForTesting
-    public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
-            new AudioAttributes.Builder()
-                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+    public static final VibrationAttributes VIBRATION_ATTRIBUTES =
+            new VibrationAttributes.Builder()
                     // vibration will bypass battery saver mode:
-                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY)
+                    .setUsage(VibrationAttributes.USAGE_COMMUNICATION_REQUEST)
                     .build();
 
+    // haptic to use for successful device entry
     public static final VibrationEffect EFFECT_CLICK =
             VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
 
@@ -276,6 +281,9 @@
                     return;
                 }
                 mGoodCaptureReceived = true;
+                if (mVibrator != null) {
+                    mVibrator.cancel();
+                }
                 mView.stopIllumination();
                 if (mServerRequest != null) {
                     mServerRequest.onAcquiredGood();
@@ -434,7 +442,7 @@
                 if (idx == event.getActionIndex()) {
                     boolean actionMoveWithinSensorArea =
                             isWithinSensorArea(udfpsView, event.getX(idx), event.getY(idx),
-                                fromUdfpsView);
+                                    fromUdfpsView);
                     if ((fromUdfpsView || actionMoveWithinSensorArea)
                             && shouldTryToDismissKeyguard()) {
                         Log.v(TAG, "onTouch | dismiss keyguard ACTION_MOVE");
@@ -508,9 +516,9 @@
 
     private boolean shouldTryToDismissKeyguard() {
         return mView.getAnimationViewController() != null
-            && mView.getAnimationViewController() instanceof UdfpsKeyguardViewController
-            && mKeyguardStateController.canDismissLockScreen()
-            && !mAttemptedToDismissKeyguard;
+                && mView.getAnimationViewController() instanceof UdfpsKeyguardViewController
+                && mKeyguardStateController.canDismissLockScreen()
+                && !mAttemptedToDismissKeyguard;
     }
 
     @Inject
@@ -542,7 +550,6 @@
             @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
         mContext = context;
         mExecution = execution;
-        // TODO (b/185124905): inject main handler and vibrator once done prototyping
         mVibrator = vibrator;
         mInflater = inflater;
         // The fingerprint manager is queried for UDFPS before this class is constructed, so the
@@ -567,6 +574,7 @@
         mConfigurationController = configurationController;
         mSystemClock = systemClock;
         mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+        mTick = lowTick();
 
         mSensorProps = findFirstUdfps();
         // At least one UDFPS sensor exists
@@ -601,6 +609,36 @@
         udfpsHapticsSimulator.setUdfpsController(this);
     }
 
+    private VibrationEffect lowTick() {
+        boolean useLowTickDefault = mContext.getResources()
+                .getBoolean(R.bool.config_udfpsUseLowTick);
+        if (Settings.Global.getFloat(
+                mContext.getContentResolver(),
+                "tick-low", useLowTickDefault ? 1 : 0) == 0) {
+            mPrimitiveTick = VibrationEffect.Composition.PRIMITIVE_TICK;
+        }
+        float tickIntensity = Settings.Global.getFloat(
+                mContext.getContentResolver(),
+                "tick-intensity",
+                mContext.getResources().getFloat(R.dimen.config_udfpsTickIntensity));
+        int tickDelay = Settings.Global.getInt(
+                mContext.getContentResolver(),
+                "tick-delay",
+                mContext.getResources().getInteger(R.integer.config_udfpsTickDelay));
+
+        VibrationEffect.Composition composition = VibrationEffect.startComposition();
+        composition.addPrimitive(mPrimitiveTick, tickIntensity, 0);
+        int primitives = 1000 / tickDelay;
+        float[] rampUp = new float[]{.48f, .58f, .69f, .83f};
+        for (int i = 0; i < rampUp.length; i++) {
+            composition.addPrimitive(mPrimitiveTick, tickIntensity * rampUp[i], tickDelay);
+        }
+        for (int i = rampUp.length; i < primitives; i++) {
+            composition.addPrimitive(mPrimitiveTick, tickIntensity, tickDelay);
+        }
+        return composition.compose();
+    }
+
     /**
      * Play haptic to signal udfps scanning started.
      */
@@ -610,9 +648,9 @@
             mVibrator.vibrate(
                     Process.myUid(),
                     mContext.getOpPackageName(),
-                    EFFECT_CLICK,
-                    "udfps-onStart",
-                    VIBRATION_SONIFICATION_ATTRIBUTES);
+                    mTick,
+                    "udfps-onStart-tick",
+                    VIBRATION_ATTRIBUTES);
         }
     }
 
@@ -998,6 +1036,7 @@
             }
         }
         mOnFingerDown = false;
+        mVibrator.cancel();
         if (mView.isIlluminationRequested()) {
             mView.stopIllumination();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 223eb78..8f4d6f6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -255,7 +255,6 @@
     private void maybeShowInputBouncer() {
         if (mShowingUdfpsBouncer && hasUdfpsBouncerShownWithMinTime()) {
             mKeyguardViewManager.showBouncer(true);
-            mKeyguardViewManager.resetAlternateAuth(false);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
new file mode 100644
index 0000000..b5d81f2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/dagger/BiometricsModule.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2021 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.biometrics.dagger
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.util.concurrency.ThreadFactory
+import dagger.Module
+import dagger.Provides
+import java.util.concurrent.Executor
+import javax.inject.Qualifier
+
+/**
+ * Dagger module for all things biometric.
+ */
+@Module
+object BiometricsModule {
+
+    /** Background [Executor] for HAL related operations. */
+    @Provides
+    @SysUISingleton
+    @JvmStatic
+    @BiometricsBackground
+    fun providesPluginExecutor(threadFactory: ThreadFactory): Executor =
+        threadFactory.buildExecutorOnNewThread("biometrics")
+}
+
+/**
+ * Background executor for HAL operations that are latency sensitive but too
+ * slow to run on the main thread. Prefer the shared executors, such as
+ * [com.android.systemui.dagger.qualifiers.Background] when a HAL is not directly involved.
+ */
+@Qualifier
+@MustBeDocumented
+@Retention(AnnotationRetention.RUNTIME)
+annotation class BiometricsBackground
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSource.java b/packages/SystemUI/src/com/android/systemui/communal/CommunalSource.java
index 99c311e..53586f5 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/CommunalSource.java
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSource.java
@@ -23,6 +23,8 @@
 
 import com.google.common.util.concurrent.ListenableFuture;
 
+import java.util.Optional;
+
 /**
  * {@link CommunalSource} defines an interface for working with a source for communal data. Clients
  * may request a communal surface that can be shown within a {@link android.view.SurfaceView}.
@@ -30,6 +32,28 @@
  */
 public interface CommunalSource {
     /**
+     * {@link Connector} defines an interface for {@link CommunalSource} instances to be generated.
+     */
+    interface Connector {
+        ListenableFuture<Optional<CommunalSource>> connect();
+    }
+
+    /**
+     * The {@link Observer} interface specifies an entity which {@link CommunalSource} listeners
+     * can be informed of changes to the source, which will require updating. Note that this deals
+     * with changes to the source itself, not content which will be updated through the
+     * {@link CommunalSource} interface.
+     */
+    interface Observer {
+        interface Callback {
+            void onSourceChanged();
+        }
+
+        void addCallback(Callback callback);
+        void removeCallback(Callback callback);
+    }
+
+    /**
      * {@link CommunalViewResult} is handed back from {@link #requestCommunalView(Context)} and
      * contains the view to be displayed and its associated controller.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalSourcePrimer.java b/packages/SystemUI/src/com/android/systemui/communal/CommunalSourcePrimer.java
new file mode 100644
index 0000000..3c2b79e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalSourcePrimer.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2021 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.communal;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import com.android.systemui.CoreStartable;
+import com.android.systemui.R;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+/**
+ * The {@link CommunalSourcePrimer} is responsible for priming SystemUI with a pre-configured
+ * Communal source. The SystemUI service binds to the component to retrieve the
+ * {@link CommunalSource}. {@link CommunalSourcePrimer} has no effect
+ * if there is no pre-defined value.
+ */
+@SysUISingleton
+public class CommunalSourcePrimer extends CoreStartable {
+    private static final String TAG = "CommunalSourcePrimer";
+    private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+    private final DelayableExecutor mMainExecutor;
+    private final CommunalSourceMonitor mMonitor;
+    private final int mBaseReconnectDelayMs;
+    private final int mMaxReconnectAttempts;
+
+    private int mReconnectAttempts = 0;
+    private Runnable mCurrentReconnectCancelable;
+    private ListenableFuture<Optional<CommunalSource>> mGetSourceFuture;
+
+    private final Optional<CommunalSource.Connector> mConnector;
+    private final Optional<CommunalSource.Observer> mObserver;
+
+    private final Runnable mConnectRunnable = new Runnable() {
+        @Override
+        public void run() {
+            mCurrentReconnectCancelable = null;
+            connect();
+        }
+    };
+
+    @Inject
+    public CommunalSourcePrimer(Context context, @Main Resources resources,
+            DelayableExecutor mainExecutor,
+            CommunalSourceMonitor monitor,
+            Optional<CommunalSource.Connector> connector,
+            Optional<CommunalSource.Observer> observer) {
+        super(context);
+        mMainExecutor = mainExecutor;
+        mMonitor = monitor;
+        mConnector = connector;
+        mObserver = observer;
+
+        mMaxReconnectAttempts = resources.getInteger(
+                R.integer.config_communalSourceMaxReconnectAttempts);
+        mBaseReconnectDelayMs = resources.getInteger(
+                R.integer.config_communalSourceReconnectBaseDelay);
+    }
+
+    @Override
+    public void start() {
+    }
+
+    private void initiateConnectionAttempt() {
+        // Reset attempts
+        mReconnectAttempts = 0;
+        mMonitor.setSource(null);
+
+        // The first attempt is always a direct invocation rather than delayed.
+        connect();
+    }
+
+    private void scheduleConnectionAttempt() {
+        // always clear cancelable if present.
+        if (mCurrentReconnectCancelable != null) {
+            mCurrentReconnectCancelable.run();
+            mCurrentReconnectCancelable = null;
+        }
+
+        if (mReconnectAttempts >= mMaxReconnectAttempts) {
+            if (DEBUG) {
+                Log.d(TAG, "exceeded max connection attempts.");
+            }
+            return;
+        }
+
+        final long reconnectDelayMs =
+                (long) Math.scalb(mBaseReconnectDelayMs, mReconnectAttempts);
+
+        if (DEBUG) {
+            Log.d(TAG,
+                    "scheduling connection attempt in " + reconnectDelayMs + "milliseconds");
+        }
+
+        mCurrentReconnectCancelable = mMainExecutor.executeDelayed(mConnectRunnable,
+                reconnectDelayMs);
+
+        mReconnectAttempts++;
+    }
+
+    @Override
+    protected void onBootCompleted() {
+        if (mObserver.isPresent()) {
+            mObserver.get().addCallback(() -> initiateConnectionAttempt());
+        }
+        initiateConnectionAttempt();
+    }
+
+    private void connect() {
+        if (DEBUG) {
+            Log.d(TAG, "attempting to communal to communal source");
+        }
+
+        if (mGetSourceFuture != null) {
+            if (DEBUG) {
+                Log.d(TAG, "canceling in-flight connection");
+            }
+            mGetSourceFuture.cancel(true);
+        }
+
+        mGetSourceFuture = mConnector.get().connect();
+        mGetSourceFuture.addListener(() -> {
+            try {
+                Optional<CommunalSource> result = mGetSourceFuture.get();
+                if (result.isPresent()) {
+                    final CommunalSource source = result.get();
+                    source.addCallback(() -> initiateConnectionAttempt());
+                    mMonitor.setSource(source);
+                } else {
+                    scheduleConnectionAttempt();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }, mMainExecutor);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index a9fb743..bc6d2f6 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -23,6 +23,7 @@
 import com.android.systemui.SystemUIAppComponentFactory;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.KeyguardSliceProvider;
+import com.android.systemui.media.taptotransfer.MediaTttChipController;
 import com.android.systemui.people.PeopleProvider;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.unfold.SysUIUnfoldComponent;
@@ -37,6 +38,7 @@
 import com.android.wm.shell.onehanded.OneHanded;
 import com.android.wm.shell.pip.Pip;
 import com.android.wm.shell.recents.RecentTasks;
+import com.android.wm.shell.sizecompatui.SizeCompatUI;
 import com.android.wm.shell.splitscreen.SplitScreen;
 import com.android.wm.shell.startingsurface.StartingSurface;
 import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
@@ -107,6 +109,9 @@
         @BindsInstance
         Builder setRecentTasks(Optional<RecentTasks> r);
 
+        @BindsInstance
+        Builder setSizeCompatUI(Optional<SizeCompatUI> s);
+
         SysUIComponent build();
     }
 
@@ -122,6 +127,8 @@
             c.getUnfoldTransitionWallpaperController().init();
         });
         getNaturalRotationUnfoldProgressProvider().ifPresent(o -> o.init());
+        // No init method needed, just needs to be gotten so that it's created.
+        getMediaTttChipController();
     }
 
     /**
@@ -168,6 +175,9 @@
      */
     Optional<NaturalRotationUnfoldProgressProvider> getNaturalRotationUnfoldProgressProvider();
 
+    /** */
+    Optional<MediaTttChipController> getMediaTttChipController();
+
     /**
      * Member injection into the supplied argument.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 3c86760..1d17fd8 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -30,6 +30,7 @@
 import com.android.systemui.appops.dagger.AppOpsModule;
 import com.android.systemui.assist.AssistModule;
 import com.android.systemui.biometrics.UdfpsHbmProvider;
+import com.android.systemui.biometrics.dagger.BiometricsModule;
 import com.android.systemui.classifier.FalsingModule;
 import com.android.systemui.communal.dagger.CommunalModule;
 import com.android.systemui.controls.dagger.ControlsModule;
@@ -38,10 +39,6 @@
 import com.android.systemui.doze.dagger.DozeComponent;
 import com.android.systemui.dreams.dagger.DreamModule;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlagManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.flags.FlagReader;
-import com.android.systemui.flags.FlagWriter;
 import com.android.systemui.flags.FlagsModule;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.log.dagger.LogModule;
@@ -55,6 +52,7 @@
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
@@ -103,6 +101,7 @@
 @Module(includes = {
             AppOpsModule.class,
             AssistModule.class,
+            BiometricsModule.class,
             ClockModule.class,
             CommunalModule.class,
             DreamModule.class,
@@ -159,12 +158,6 @@
         return state;
     }
 
-    @Binds
-    abstract FlagReader provideFlagReader(FeatureFlagManager impl);
-
-    @Binds
-    abstract FlagWriter provideFlagWriter(FeatureFlagManager impl);
-
     @BindsOptionalOf
     abstract CommandQueue optionalCommandQueue();
 
@@ -213,14 +206,15 @@
             NotificationInterruptStateProvider interruptionStateProvider,
             ZenModeController zenModeController, NotificationLockscreenUserManager notifUserManager,
             NotificationGroupManagerLegacy groupManager, NotificationEntryManager entryManager,
-            NotifPipeline notifPipeline, SysUiState sysUiState, FeatureFlags featureFlags,
-            DumpManager dumpManager, @Main Executor sysuiMainExecutor) {
+            NotifPipeline notifPipeline, SysUiState sysUiState,
+            NotifPipelineFlags notifPipelineFlags, DumpManager dumpManager,
+            @Main Executor sysuiMainExecutor) {
         return Optional.ofNullable(BubblesManager.create(context, bubblesOptional,
                 notificationShadeWindowController, statusBarStateController, shadeController,
                 configurationController, statusBarService, notificationManager,
                 visibilityProvider,
                 interruptionStateProvider, zenModeController, notifUserManager,
-                groupManager, entryManager, notifPipeline, sysUiState, featureFlags, dumpManager,
-                sysuiMainExecutor));
+                groupManager, entryManager, notifPipeline, sysUiState, notifPipelineFlags,
+                dumpManager, sysuiMainExecutor));
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
index d8b7742..543ba8f 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java
@@ -20,13 +20,13 @@
 
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.tv.TvWMComponent;
-import com.android.wm.shell.dagger.TvWMShellModule;
-import com.android.wm.shell.dagger.WMShellModule;
 import com.android.wm.shell.ShellCommandHandler;
 import com.android.wm.shell.ShellInit;
 import com.android.wm.shell.TaskViewFactory;
 import com.android.wm.shell.apppairs.AppPairs;
 import com.android.wm.shell.bubbles.Bubbles;
+import com.android.wm.shell.dagger.TvWMShellModule;
+import com.android.wm.shell.dagger.WMShellModule;
 import com.android.wm.shell.dagger.WMSingleton;
 import com.android.wm.shell.displayareahelper.DisplayAreaHelper;
 import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
@@ -34,6 +34,7 @@
 import com.android.wm.shell.onehanded.OneHanded;
 import com.android.wm.shell.pip.Pip;
 import com.android.wm.shell.recents.RecentTasks;
+import com.android.wm.shell.sizecompatui.SizeCompatUI;
 import com.android.wm.shell.splitscreen.SplitScreen;
 import com.android.wm.shell.startingsurface.StartingSurface;
 import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
@@ -115,4 +116,7 @@
 
     @WMSingleton
     Optional<RecentTasks> getRecentTasks();
+
+    @WMSingleton
+    SizeCompatUI getSizeCompatUI();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 765c245..d27c39a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -16,6 +16,10 @@
 
 package com.android.systemui.doze;
 
+import static android.os.PowerManager.GO_TO_SLEEP_REASON_TIMEOUT;
+
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
+
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -31,11 +35,13 @@
 import android.provider.Settings;
 import android.util.IndentingPrintWriter;
 
+import com.android.internal.R;
 import com.android.systemui.doze.dagger.BrightnessSensor;
 import com.android.systemui.doze.dagger.DozeScope;
 import com.android.systemui.doze.dagger.WrappedService;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.util.sensors.AsyncSensorManager;
 
@@ -57,6 +63,12 @@
             "com.android.systemui.doze.AOD_BRIGHTNESS";
     protected static final String BRIGHTNESS_BUCKET = "brightness_bucket";
 
+    /**
+     * Just before the screen times out from user inactivity, DisplayPowerController dims the screen
+     * brightness to the lower of {@link #mScreenBrightnessDim}, or the current brightness minus
+     * this amount.
+     */
+    private final float mScreenBrightnessMinimumDimAmountFloat;
     private final Context mContext;
     private final DozeMachine.Service mDozeService;
     private final DozeHost mDozeHost;
@@ -87,6 +99,8 @@
      */
     private int mDebugBrightnessBucket = -1;
 
+    private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
+
     @Inject
     public DozeScreenBrightness(
             Context context,
@@ -98,8 +112,8 @@
             WakefulnessLifecycle wakefulnessLifecycle,
             DozeParameters dozeParameters,
             DevicePostureController devicePostureController,
-            DozeLog dozeLog
-    ) {
+            DozeLog dozeLog,
+            UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
         mContext = context;
         mDozeService = service;
         mSensorManager = sensorManager;
@@ -111,6 +125,10 @@
         mDozeHost = host;
         mHandler = handler;
         mDozeLog = dozeLog;
+        mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+
+        mScreenBrightnessMinimumDimAmountFloat = context.getResources().getFloat(
+                R.dimen.config_screenBrightnessMinimumDimAmountFloat);
 
         mDefaultDozeBrightness = alwaysOnDisplayPolicy.defaultDozeBrightness;
         mScreenBrightnessDim = alwaysOnDisplayPolicy.dimBrightness;
@@ -163,14 +181,15 @@
         }
     }
 
-    private void updateBrightnessAndReady(boolean force) {
+    public void updateBrightnessAndReady(boolean force) {
         if (force || mRegistered || mDebugBrightnessBucket != -1) {
             int sensorValue = mDebugBrightnessBucket == -1
                     ? mLastSensorValue : mDebugBrightnessBucket;
             int brightness = computeBrightness(sensorValue);
             boolean brightnessReady = brightness > 0;
             if (brightnessReady) {
-                mDozeService.setDozeScreenBrightness(clampToUserSetting(brightness));
+                mDozeService.setDozeScreenBrightness(
+                        clampToDimBrightnessForScreenOff(clampToUserSetting(brightness)));
             }
 
             int scrimOpacity = -1;
@@ -243,13 +262,24 @@
     /**
      * Clamp the brightness to the dim brightness value used by PowerManagerService just before the
      * device times out and goes to sleep, if we are sleeping from a timeout. This ensures that we
-     * don't raise the brightness back to the user setting before playing the screen off animation.
+     * don't raise the brightness back to the user setting before or during the screen off
+     * animation.
      */
     private int clampToDimBrightnessForScreenOff(int brightness) {
-        if (mDozeParameters.shouldControlUnlockedScreenOff()
-                && mWakefulnessLifecycle.getLastSleepReason()
-                == PowerManager.GO_TO_SLEEP_REASON_TIMEOUT) {
-            return Math.min(mScreenBrightnessDim, brightness);
+        final boolean screenTurningOff =
+                mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()
+                        || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_GOING_TO_SLEEP;
+        if (screenTurningOff
+                && mWakefulnessLifecycle.getLastSleepReason() == GO_TO_SLEEP_REASON_TIMEOUT) {
+            return Math.max(
+                    PowerManager.BRIGHTNESS_OFF,
+                    // Use the lower of either the dim brightness, or the current brightness reduced
+                    // by the minimum dim amount. This is the same logic used in
+                    // DisplayPowerController#updatePowerState to apply a minimum dim amount.
+                    Math.min(
+                            brightness - (int) Math.floor(
+                                    mScreenBrightnessMinimumDimAmountFloat * 255),
+                            mScreenBrightnessDim));
         } else {
             return brightness;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
index 908397b..3631938 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java
@@ -77,6 +77,7 @@
     private final Provider<UdfpsController> mUdfpsControllerProvider;
     @Nullable private UdfpsController mUdfpsController;
     private final DozeLog mDozeLog;
+    private final DozeScreenBrightness mDozeScreenBrightness;
 
     private int mPendingScreenState = Display.STATE_UNKNOWN;
     private SettableWakeLock mWakeLock;
@@ -90,7 +91,8 @@
             WakeLock wakeLock,
             AuthController authController,
             Provider<UdfpsController> udfpsControllerProvider,
-            DozeLog dozeLog) {
+            DozeLog dozeLog,
+            DozeScreenBrightness dozeScreenBrightness) {
         mDozeService = service;
         mHandler = handler;
         mParameters = parameters;
@@ -99,6 +101,7 @@
         mAuthController = authController;
         mUdfpsControllerProvider = udfpsControllerProvider;
         mDozeLog = dozeLog;
+        mDozeScreenBrightness = dozeScreenBrightness;
 
         updateUdfpsController();
         if (mUdfpsController == null) {
@@ -209,6 +212,12 @@
         if (screenState != Display.STATE_UNKNOWN) {
             if (DEBUG) Log.d(TAG, "setDozeScreenState(" + screenState + ")");
             mDozeService.setDozeScreenState(screenState);
+            if (screenState == Display.STATE_DOZE) {
+                // If we're entering doze, update the doze screen brightness. We might have been
+                // clamping it to the dim brightness during the screen off animation, and we should
+                // now change it to the brightness we actually want according to the sensor.
+                mDozeScreenBrightness.updateBrightnessAndReady(false /* force */);
+            }
             mPendingScreenState = Display.STATE_UNKNOWN;
             mWakeLock.setAcquired(false);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 5c3e07f..239109a 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.doze;
 
+import static com.android.systemui.doze.DozeLog.REASON_SENSOR_QUICK_PICKUP;
+import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
 import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_DISPLAY;
 import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
 
@@ -98,6 +100,7 @@
     private final DozeLog mDozeLog;
     private final SecureSettings mSecureSettings;
     private final DevicePostureController mDevicePostureController;
+    private final AuthController mAuthController;
     private final boolean mScreenOffUdfpsEnabled;
 
     // Sensors
@@ -115,6 +118,7 @@
     private boolean mListening;
     private boolean mListeningTouchScreenSensors;
     private boolean mListeningProxSensors;
+    private boolean mUdfpsEnrolled;
 
     @DevicePostureController.DevicePostureInt
     private int mDevicePosture;
@@ -169,10 +173,11 @@
                 config.screenOffUdfpsEnabled(KeyguardUpdateMonitor.getCurrentUser());
         mDevicePostureController = devicePostureController;
         mDevicePosture = mDevicePostureController.getDevicePosture();
+        mAuthController = authController;
 
-        boolean udfpsEnrolled =
-                authController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser());
-        boolean alwaysOn = mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT);
+        mUdfpsEnrolled =
+                mAuthController.isUdfpsEnrolled(KeyguardUpdateMonitor.getCurrentUser());
+        mAuthController.addCallback(mAuthControllerCallback);
         mTriggerSensors = new TriggerSensor[] {
                 new TriggerSensor(
                         mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION),
@@ -221,7 +226,7 @@
                         findSensor(config.udfpsLongPressSensorType()),
                         "doze_pulse_on_auth",
                         true /* settingDef */,
-                        udfpsEnrolled && (alwaysOn || mScreenOffUdfpsEnabled),
+                        udfpsLongPressConfigured(),
                         DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS,
                         true /* reports touch coordinates */,
                         true /* touchscreen */,
@@ -230,7 +235,8 @@
                 new PluginSensor(
                         new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
                         Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
-                        mConfig.wakeScreenGestureAvailable() && alwaysOn,
+                        mConfig.wakeScreenGestureAvailable()
+                          && mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT),
                         DozeLog.REASON_SENSOR_WAKE_UP_PRESENCE,
                         false /* reports touch coordinates */,
                         false /* touchscreen */),
@@ -246,8 +252,7 @@
                         findSensor(config.quickPickupSensorType()),
                         Settings.Secure.DOZE_QUICK_PICKUP_GESTURE,
                         true /* setting default */,
-                        config.quickPickupSensorEnabled(KeyguardUpdateMonitor.getCurrentUser())
-                                && udfpsEnrolled,
+                        quickPickUpConfigured(),
                         DozeLog.REASON_SENSOR_QUICK_PICKUP,
                         false /* requiresTouchCoordinates */,
                         false /* requiresTouchscreen */,
@@ -265,6 +270,16 @@
         mDevicePostureController.addCallback(mDevicePostureCallback);
     }
 
+    private boolean udfpsLongPressConfigured() {
+        return mUdfpsEnrolled
+                && (mConfig.alwaysOnEnabled(UserHandle.USER_CURRENT) || mScreenOffUdfpsEnabled);
+    }
+
+    private boolean quickPickUpConfigured() {
+        return mUdfpsEnrolled
+                && mConfig.quickPickupSensorEnabled(KeyguardUpdateMonitor.getCurrentUser());
+    }
+
     /**
      *  Unregister all sensors and callbacks.
      */
@@ -276,6 +291,7 @@
         mProximitySensor.pause();
 
         mDevicePostureController.removeCallback(mDevicePostureCallback);
+        mAuthController.removeCallback(mAuthControllerCallback);
     }
 
     /**
@@ -450,6 +466,7 @@
         pw.println("mSelectivelyRegisterProxSensors=" + mSelectivelyRegisterProxSensors);
         pw.println("mListeningProxSensors=" + mListeningProxSensors);
         pw.println("mScreenOffUdfpsEnabled=" + mScreenOffUdfpsEnabled);
+        pw.println("mUdfpsEnrolled=" + mUdfpsEnrolled);
         IndentingPrintWriter idpw = new IndentingPrintWriter(pw);
         idpw.increaseIndent();
         for (TriggerSensor s : mTriggerSensors) {
@@ -468,7 +485,7 @@
     @VisibleForTesting
     class TriggerSensor extends TriggerEventListener {
         @NonNull final Sensor[] mSensors; // index = posture, value = sensor
-        final boolean mConfigured;
+        boolean mConfigured;
         final int mPulseReason;
         private final String mSetting;
         private final boolean mReportsTouchCoordinates;
@@ -496,10 +513,10 @@
                     true /* settingDef */,
                     configured,
                     pulseReason,
-                    false /* ignoresSetting */,
-                    false /* requiresProx */,
                     reportsTouchCoordinates,
-                    requiresTouchscreen
+                    requiresTouchscreen,
+                    false /* ignoresSetting */,
+                    false /* requiresProx */
             );
         }
 
@@ -606,8 +623,18 @@
             updateListening();
         }
 
+        /**
+         * Update configured state.
+         */
+        public void setConfigured(boolean configured) {
+            if (mConfigured == configured) return;
+            mConfigured = configured;
+            updateListening();
+        }
+
         public void updateListening() {
             final Sensor sensor = mSensors[mPosture];
+
             if (!mConfigured || sensor == null) return;
             if (mRequested && !mDisabled && (enabledBySetting() || mIgnoresSetting)) {
                 if (!mRegistered) {
@@ -791,6 +818,30 @@
         }
     };
 
+    private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
+        @Override
+        public void onAllAuthenticatorsRegistered() {
+            updateUdfpsEnrolled();
+        }
+
+        @Override
+        public void onEnrollmentsChanged() {
+            updateUdfpsEnrolled();
+        }
+
+        private void updateUdfpsEnrolled() {
+            mUdfpsEnrolled = mAuthController.isUdfpsEnrolled(
+                    KeyguardUpdateMonitor.getCurrentUser());
+            for (TriggerSensor sensor : mTriggerSensors) {
+                if (REASON_SENSOR_QUICK_PICKUP == sensor.mPulseReason) {
+                    sensor.setConfigured(quickPickUpConfigured());
+                } else if (REASON_SENSOR_UDFPS_LONG_PRESS == sensor.mPulseReason) {
+                    sensor.setConfigured(udfpsLongPressConfigured());
+                }
+            }
+        }
+    };
+
     public interface Callback {
 
         /**
diff --git a/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialog.kt b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialog.kt
new file mode 100644
index 0000000..42f3512
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialog.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2021 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.fgsmanager
+
+import android.content.Context
+import android.os.Bundle
+import android.text.format.DateUtils
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.annotation.GuardedBy
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.android.systemui.R
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.fgsmanager.FgsManagerDialogController.RunningApp
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.time.SystemClock
+import java.util.concurrent.Executor
+
+/**
+ * Dialog which shows a list of running foreground services and offers controls to them
+ */
+class FgsManagerDialog(
+    context: Context,
+    private val executor: Executor,
+    @Background private val backgroundExecutor: Executor,
+    private val systemClock: SystemClock,
+    private val fgsManagerDialogController: FgsManagerDialogController
+) : SystemUIDialog(context, R.style.Theme_SystemUI_Dialog) {
+
+    private val appListRecyclerView: RecyclerView = RecyclerView(this.context)
+    private val adapter: AppListAdapter = AppListAdapter()
+
+    init {
+        setTitle(R.string.fgs_manager_dialog_title)
+        setView(appListRecyclerView)
+    }
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        appListRecyclerView.layoutManager = LinearLayoutManager(context)
+        fgsManagerDialogController.registerDialogForChanges(
+                object : FgsManagerDialogController.FgsManagerDialogCallback {
+                    override fun onRunningAppsChanged(apps: List<RunningApp>) {
+                        executor.execute {
+                            adapter.setData(apps)
+                        }
+                    }
+                }
+        )
+        appListRecyclerView.adapter = adapter
+        backgroundExecutor.execute { adapter.setData(fgsManagerDialogController.runningAppList) }
+    }
+
+    private inner class AppListAdapter : RecyclerView.Adapter<AppItemViewHolder>() {
+        private val lock = Any()
+
+        @GuardedBy("lock")
+        private val data: MutableList<RunningApp> = ArrayList()
+        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppItemViewHolder {
+            return AppItemViewHolder(LayoutInflater.from(context)
+                            .inflate(R.layout.fgs_manager_app_item, parent, false))
+        }
+
+        override fun onBindViewHolder(holder: AppItemViewHolder, position: Int) {
+            var runningApp: RunningApp
+            synchronized(lock) {
+                runningApp = data[position]
+            }
+            with(holder) {
+                iconView.setImageDrawable(runningApp.mIcon)
+                appLabelView.text = runningApp.mAppLabel
+                durationView.text = DateUtils.formatDuration(
+                        Math.max(systemClock.elapsedRealtime() - runningApp.mTimeStarted, 60000),
+                        DateUtils.LENGTH_MEDIUM)
+                stopButton.setOnClickListener {
+                    fgsManagerDialogController
+                            .stopAllFgs(runningApp.mUserId, runningApp.mPackageName)
+                }
+            }
+        }
+
+        override fun getItemCount(): Int {
+            synchronized(lock) { return data.size }
+        }
+
+        fun setData(newData: List<RunningApp>) {
+            var oldData: List<RunningApp>
+            synchronized(lock) {
+                oldData = ArrayList(data)
+                data.clear()
+                data.addAll(newData)
+            }
+
+            DiffUtil.calculateDiff(object : DiffUtil.Callback() {
+                override fun getOldListSize(): Int {
+                    return oldData.size
+                }
+
+                override fun getNewListSize(): Int {
+                    return newData.size
+                }
+
+                override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int):
+                        Boolean {
+                    return oldData[oldItemPosition] == newData[newItemPosition]
+                }
+
+                override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int):
+                        Boolean {
+                    return true // TODO, look into updating the time subtext
+                }
+            }).dispatchUpdatesTo(this)
+        }
+    }
+
+    private class AppItemViewHolder(parent: View) : RecyclerView.ViewHolder(parent) {
+        val appLabelView: TextView = parent.requireViewById(R.id.fgs_manager_app_item_label)
+        val durationView: TextView = parent.requireViewById(R.id.fgs_manager_app_item_duration)
+        val iconView: ImageView = parent.requireViewById(R.id.fgs_manager_app_item_icon)
+        val stopButton: Button = parent.requireViewById(R.id.fgs_manager_app_item_stop_button)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogController.kt b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogController.kt
new file mode 100644
index 0000000..159ed39
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogController.kt
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2021 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.fgsmanager
+
+import android.content.pm.PackageManager
+import android.content.pm.PackageManager.NameNotFoundException
+import android.graphics.drawable.Drawable
+import android.os.Handler
+import android.os.UserHandle
+import android.util.ArrayMap
+import android.util.Log
+import androidx.annotation.GuardedBy
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.statusbar.policy.RunningFgsController
+import com.android.systemui.statusbar.policy.RunningFgsController.UserPackageTime
+import javax.inject.Inject
+
+/**
+ * Controls events relevant to FgsManagerDialog
+ */
+class FgsManagerDialogController @Inject constructor(
+    private val packageManager: PackageManager,
+    @Background private val backgroundHandler: Handler,
+    private val runningFgsController: RunningFgsController
+) : RunningFgsController.Callback {
+    private val lock = Any()
+    private val clearCacheToken = Any()
+
+    @GuardedBy("lock")
+    private var runningApps: Map<UserPackageTime, RunningApp>? = null
+    @GuardedBy("lock")
+    private var listener: FgsManagerDialogCallback? = null
+
+    interface FgsManagerDialogCallback {
+        fun onRunningAppsChanged(apps: List<RunningApp>)
+    }
+
+    data class RunningApp(
+        val mUserId: Int,
+        val mPackageName: String,
+        val mAppLabel: CharSequence,
+        val mIcon: Drawable,
+        val mTimeStarted: Long
+    )
+
+    val runningAppList: List<RunningApp>
+        get() {
+            synchronized(lock) {
+                if (runningApps == null) {
+                    onFgsPackagesChangedLocked(runningFgsController.getPackagesWithFgs())
+                }
+                return convertToRunningAppList(runningApps!!)
+            }
+        }
+
+    fun registerDialogForChanges(callback: FgsManagerDialogCallback) {
+        synchronized(lock) {
+            runningFgsController.addCallback(this)
+            listener = callback
+            backgroundHandler.removeCallbacksAndMessages(clearCacheToken)
+        }
+    }
+
+    fun onFinishDialog() {
+        synchronized(lock) {
+            listener = null
+            // Keep data such as icons cached for some time since loading can be slow
+            backgroundHandler.postDelayed(
+                    {
+                        synchronized(lock) {
+                            runningFgsController.removeCallback(this)
+                            runningApps = null
+                        }
+                    }, clearCacheToken, RUNNING_APP_CACHE_TIMEOUT_MILLIS)
+        }
+    }
+
+    private fun onRunningAppsChanged(apps: ArrayMap<UserPackageTime, RunningApp>) {
+        listener?.let {
+            backgroundHandler.post { it.onRunningAppsChanged(convertToRunningAppList(apps)) }
+        }
+    }
+
+    override fun onFgsPackagesChanged(packages: List<UserPackageTime>) {
+        backgroundHandler.post {
+            synchronized(lock) { onFgsPackagesChangedLocked(packages) }
+        }
+    }
+
+    /**
+     * Run on background thread
+     */
+    private fun onFgsPackagesChangedLocked(packages: List<UserPackageTime>) {
+        val newRunningApps = ArrayMap<UserPackageTime, RunningApp>()
+        for (packageWithFgs in packages) {
+            val ra = runningApps?.get(packageWithFgs)
+            if (ra == null) {
+                val userId = packageWithFgs.userId
+                val packageName = packageWithFgs.packageName
+                try {
+                    val ai = packageManager.getApplicationInfo(packageName, 0)
+                    var icon = packageManager.getApplicationIcon(ai)
+                    icon = packageManager.getUserBadgedIcon(icon,
+                            UserHandle.of(userId))
+                    val label = packageManager.getApplicationLabel(ai)
+                    newRunningApps[packageWithFgs] = RunningApp(userId, packageName,
+                            label, icon, packageWithFgs.startTimeMillis)
+                } catch (e: NameNotFoundException) {
+                    Log.e(LOG_TAG,
+                            "Application info not found: $packageName", e)
+                }
+            } else {
+                newRunningApps[packageWithFgs] = ra
+            }
+        }
+        runningApps = newRunningApps
+        onRunningAppsChanged(newRunningApps)
+    }
+
+    fun stopAllFgs(userId: Int, packageName: String) {
+        runningFgsController.stopFgs(userId, packageName)
+    }
+
+    companion object {
+        private val LOG_TAG = FgsManagerDialogController::class.java.simpleName
+        private const val RUNNING_APP_CACHE_TIMEOUT_MILLIS: Long = 20_000
+
+        private fun convertToRunningAppList(apps: Map<UserPackageTime, RunningApp>):
+                List<RunningApp> {
+            val result = mutableListOf<RunningApp>()
+            result.addAll(apps.values)
+            result.sortWith { a: RunningApp, b: RunningApp ->
+                b.mTimeStarted.compareTo(a.mTimeStarted)
+            }
+            return result
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogFactory.kt
new file mode 100644
index 0000000..2874929
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/fgsmanager/FgsManagerDialogFactory.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 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.fgsmanager
+
+import android.content.Context
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.animation.DialogLaunchAnimator
+import android.content.DialogInterface
+import android.view.View
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.util.time.SystemClock
+import java.util.concurrent.Executor
+import javax.inject.Inject
+
+/**
+ * Factory to create [FgsManagerDialog] instances
+ */
+@SysUISingleton
+class FgsManagerDialogFactory
+@Inject constructor(
+    private val context: Context,
+    @Main private val executor: Executor,
+    @Background private val backgroundExecutor: Executor,
+    private val systemClock: SystemClock,
+    private val dialogLaunchAnimator: DialogLaunchAnimator,
+    private val fgsManagerDialogController: FgsManagerDialogController
+) {
+
+    val lock = Any()
+
+    companion object {
+        private var fgsManagerDialog: FgsManagerDialog? = null
+    }
+
+    /**
+     * Creates the dialog if it doesn't exist
+     */
+    fun create(viewLaunchedFrom: View?) {
+        if (fgsManagerDialog == null) {
+            fgsManagerDialog = FgsManagerDialog(context, executor, backgroundExecutor,
+                    systemClock, fgsManagerDialogController)
+            fgsManagerDialog!!.setOnDismissListener { i: DialogInterface? ->
+                fgsManagerDialogController.onFinishDialog()
+                fgsManagerDialog = null
+            }
+            dialogLaunchAnimator.showFromView(fgsManagerDialog!!, viewLaunchedFrom!!)
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
index 5f7ad58..fbb78c8 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlags.java
@@ -16,139 +16,10 @@
 
 package com.android.systemui.flags;
 
-import android.content.Context;
-import android.util.FeatureFlagUtils;
-import android.util.Log;
-import android.widget.Toast;
-
-import com.android.systemui.dagger.SysUISingleton;
-
-import javax.inject.Inject;
-
 /**
  * Class to manage simple DeviceConfig-based feature flags.
  *
  * See {@link Flags} for instructions on defining new flags.
  */
-@SysUISingleton
-public class FeatureFlags {
-    private final FlagReader mFlagReader;
-    private final Context mContext;
-
-    @Inject
-    public FeatureFlags(FlagReader flagReader, Context context) {
-        mFlagReader = flagReader;
-        mContext = context;
-    }
-
-    /**
-     * @param flag The {@link BooleanFlag} of interest.
-     * @return The value of the flag.
-     */
-    public boolean isEnabled(BooleanFlag flag) {
-        return mFlagReader.isEnabled(flag);
-    }
-
-    public void assertLegacyPipelineEnabled() {
-        if (isNewNotifPipelineRenderingEnabled()) {
-            throw new IllegalStateException("Old pipeline code running w/ new pipeline enabled");
-        }
-    }
-
-    public boolean checkLegacyPipelineEnabled() {
-        if (!isNewNotifPipelineRenderingEnabled()) {
-            return true;
-        }
-        Log.d("NotifPipeline", "Old pipeline code running w/ new pipeline enabled",
-                new Exception());
-        Toast.makeText(mContext, "Old pipeline code running!", Toast.LENGTH_SHORT).show();
-        return false;
-    }
-
-    public boolean isNewNotifPipelineRenderingEnabled() {
-        return isEnabled(Flags.NEW_NOTIFICATION_PIPELINE_RENDERING);
-    }
-
-    /** */
-    public boolean useNewLockscreenAnimations() {
-        return isEnabled(Flags.LOCKSCREEN_ANIMATIONS);
-    }
-
-    public boolean isPeopleTileEnabled() {
-        return isEnabled(Flags.PEOPLE_TILE);
-    }
-
-    public boolean isMonetEnabled() {
-        return isEnabled(Flags.MONET);
-    }
-
-    public boolean isPMLiteEnabled() {
-        return isEnabled(Flags.POWER_MENU_LITE);
-    }
-
-    public boolean isChargingRippleEnabled() {
-        return isEnabled(Flags.CHARGING_RIPPLE);
-    }
-
-    public boolean isOngoingCallStatusBarChipEnabled() {
-        return isEnabled(Flags.ONGOING_CALL_STATUS_BAR_CHIP);
-    }
-
-    public boolean isOngoingCallInImmersiveEnabled() {
-        return isOngoingCallStatusBarChipEnabled() && isEnabled(Flags.ONGOING_CALL_IN_IMMERSIVE);
-    }
-
-    public boolean isOngoingCallInImmersiveChipTapEnabled() {
-        return isOngoingCallInImmersiveEnabled()
-                && isEnabled(Flags.ONGOING_CALL_IN_IMMERSIVE_CHIP_TAP);
-    }
-
-    public boolean isSmartspaceEnabled() {
-        return isEnabled(Flags.SMARTSPACE);
-    }
-
-    public boolean isSmartspaceDedupingEnabled() {
-        return isSmartspaceEnabled() && isEnabled(Flags.SMARTSPACE_DEDUPING);
-    }
-
-    public boolean isNewKeyguardSwipeAnimationEnabled() {
-        return isEnabled(Flags.NEW_UNLOCK_SWIPE_ANIMATION);
-    }
-
-    public boolean isKeyguardQsUserDetailsShortcutEnabled() {
-        return isEnabled(Flags.QS_USER_DETAIL_SHORTCUT);
-    }
-
-    public boolean isSmartSpaceSharedElementTransitionEnabled() {
-        return isEnabled(Flags.SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED);
-    }
-
-    /** Whether or not to use the provider model behavior for the status bar icons */
-    public boolean isCombinedStatusBarSignalIconsEnabled() {
-        return isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS);
-    }
-
-    /** System setting for provider model behavior */
-    public boolean isProviderModelSettingEnabled() {
-        return FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
-    }
-
-    /**
-     * Use the new version of the user switcher
-     */
-    public boolean useNewUserSwitcher() {
-        return isEnabled(Flags.NEW_USER_SWITCHER);
-    }
-
-    /**
-     * Use the new single view QS headers
-     */
-    public boolean useCombinedQSHeaders() {
-        return isEnabled(Flags.COMBINED_QS_HEADERS);
-    }
-
-    /** static method for the system setting */
-    public static boolean isProviderModelSettingEnabled(Context context) {
-        return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
-    }
+public interface FeatureFlags extends FlagReader {
 }
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
similarity index 97%
rename from packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java
rename to packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
index acfa3c8..0ee47a7 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsDebug.java
@@ -60,7 +60,7 @@
  * To restore a flag back to its default, leave the `--ez value <0|1>` off of the command.
  */
 @SysUISingleton
-public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
+public class FeatureFlagsDebug implements FeatureFlags, Dumpable {
     private static final String TAG = "SysUIFlags";
 
     private final FlagManager mFlagManager;
@@ -69,7 +69,7 @@
     private final Map<Integer, Boolean> mBooleanFlagCache = new HashMap<>();
 
     @Inject
-    public FeatureFlagManager(
+    public FeatureFlagsDebug(
             FlagManager flagManager,
             Context context,
             SecureSettings secureSettings,
@@ -126,7 +126,6 @@
     }
 
     /** Set whether a given {@link BooleanFlag} is enabled or not. */
-    @Override
     public void setEnabled(int id, boolean value) {
         Boolean currentValue = isEnabledInternal(id);
         if (currentValue != null && currentValue == value) {
diff --git a/packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
similarity index 90%
rename from packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java
rename to packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
index 0934b32..bd6cb66 100644
--- a/packages/SystemUI/src-release/com/android/systemui/flags/FeatureFlagManager.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagsRelease.java
@@ -36,10 +36,10 @@
  * how to set flags.
  */
 @SysUISingleton
-public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
+public class FeatureFlagsRelease implements FeatureFlags, Dumpable {
     SparseBooleanArray mAccessedFlags = new SparseBooleanArray();
     @Inject
-    public FeatureFlagManager(DumpManager dumpManager) {
+    public FeatureFlagsRelease(DumpManager dumpManager) {
         dumpManager.registerDumpable("SysUIFlags", this);
     }
 
@@ -59,8 +59,6 @@
         mAccessedFlags.append(key, defaultValue);
         return defaultValue;
     }
-    @Override
-    public void setEnabled(int key, boolean value) {}
 
     @Override
     public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index ee24f45..458cdc1f 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -33,7 +33,7 @@
  * On public release builds, flags will always return their default value. There is no way to
  * change their value on release builds.
  *
- * See {@link FeatureFlagManager} for instructions on flipping the flags via adb.
+ * See {@link FeatureFlagsDebug} for instructions on flipping the flags via adb.
  */
 public class Flags {
     public static final BooleanFlag TEAMFOOD = new BooleanFlag(1, false);
@@ -46,6 +46,10 @@
     public static final BooleanFlag NOTIFICATION_UPDATES =
             new BooleanFlag(102, true);
 
+    public static final BooleanFlag NOTIFICATION_PIPELINE_DEVELOPER_LOGGING =
+            new BooleanFlag(103, false);
+
+
     /***************************************/
     // 200 - keyguard/lockscreen
     public static final BooleanFlag KEYGUARD_LAYOUT =
@@ -92,6 +96,9 @@
 
     /***************************************/
     // 600- status bar
+    public static final BooleanFlag STATUS_BAR_PROVIDER_MODEL =
+            new BooleanFlag(600, false);
+
     public static final BooleanFlag COMBINED_STATUS_BAR_SIGNAL_ICONS =
             new BooleanFlag(601, false);
 
@@ -111,6 +118,10 @@
     public static final BooleanFlag MONET =
             new BooleanFlag(800, true, R.bool.flag_monet);
 
+    /***************************************/
+    // 900 - media
+    public static final BooleanFlag MEDIA_TAP_TO_TRANSFER = new BooleanFlag(900, false);
+
     // Pay no attention to the reflection behind the curtain.
     // ========================== Curtain ==========================
     // |                                                           |
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index b45dc52..10878dc 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -42,7 +42,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.HashMap;
 
@@ -308,22 +307,22 @@
             return instantiateWithInjections(context, className, arguments);
         }
 
-        private Fragment instantiateWithInjections(Context context, String className,
-                Bundle args) {
-            Method method = mManager.getInjectionMap().get(className);
-            if (method != null) {
+        private Fragment instantiateWithInjections(
+                Context context, String className, Bundle args) {
+            FragmentService.FragmentInstantiationInfo fragmentInstantiationInfo =
+                    mManager.getInjectionMap().get(className);
+            if (fragmentInstantiationInfo != null) {
                 try {
-                    Fragment f = (Fragment) method.invoke(mManager.getFragmentCreator());
+                    Fragment f = (Fragment) fragmentInstantiationInfo
+                            .mMethod
+                            .invoke(fragmentInstantiationInfo.mDaggerComponent);
                     // Setup the args, taken from Fragment#instantiate.
                     if (args != null) {
                         args.setClassLoader(f.getClass().getClassLoader());
                         f.setArguments(args);
                     }
                     return f;
-                } catch (IllegalAccessException e) {
-                    throw new Fragment.InstantiationException("Unable to instantiate " + className,
-                            e);
-                } catch (InvocationTargetException e) {
+                } catch (IllegalAccessException | InvocationTargetException e) {
                     throw new Fragment.InstantiationException("Unable to instantiate " + className,
                             e);
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
index 4f5a969..2a5e653 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentService.java
@@ -18,13 +18,13 @@
 import android.content.res.Configuration;
 import android.os.Handler;
 import android.util.ArrayMap;
+import android.util.Log;
 import android.view.View;
 
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.qs.QSFragment;
-import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import java.io.FileDescriptor;
@@ -46,9 +46,14 @@
     private static final String TAG = "FragmentService";
 
     private final ArrayMap<View, FragmentHostState> mHosts = new ArrayMap<>();
-    private final ArrayMap<String, Method> mInjectionMap = new ArrayMap<>();
+    /**
+     * A map with the means to create fragments via Dagger injection.
+     *
+     * key: the fragment class name.
+     * value: see {@link FragmentInstantiationInfo}.
+     */
+    private final ArrayMap<String, FragmentInstantiationInfo> mInjectionMap = new ArrayMap<>();
     private final Handler mHandler = new Handler();
-    private final FragmentCreator mFragmentCreator;
 
     private ConfigurationController.ConfigurationListener mConfigurationListener =
             new ConfigurationController.ConfigurationListener() {
@@ -65,26 +70,31 @@
             FragmentCreator.Factory fragmentCreatorFactory,
             ConfigurationController configurationController,
             DumpManager dumpManager) {
-        mFragmentCreator = fragmentCreatorFactory.build();
-        initInjectionMap();
+        addFragmentInstantiationProvider(fragmentCreatorFactory.build());
         configurationController.addCallback(mConfigurationListener);
 
         dumpManager.registerDumpable(getClass().getSimpleName(), this);
     }
 
-    ArrayMap<String, Method> getInjectionMap() {
+    ArrayMap<String, FragmentInstantiationInfo> getInjectionMap() {
         return mInjectionMap;
     }
 
-    FragmentCreator getFragmentCreator() {
-        return mFragmentCreator;
-    }
-
-    private void initInjectionMap() {
-        for (Method method : FragmentCreator.class.getDeclaredMethods()) {
+    /**
+     * Adds a new Dagger component object that provides method(s) to create fragments via injection.
+     */
+    public void addFragmentInstantiationProvider(Object daggerComponent) {
+        for (Method method : daggerComponent.getClass().getDeclaredMethods()) {
             if (Fragment.class.isAssignableFrom(method.getReturnType())
                     && (method.getModifiers() & Modifier.PUBLIC) != 0) {
-                mInjectionMap.put(method.getReturnType().getName(), method);
+                String fragmentName = method.getReturnType().getName();
+                if (mInjectionMap.containsKey(fragmentName)) {
+                    Log.w(TAG, "Fragment " + fragmentName + " is already provided by different"
+                            + " Dagger component; Not adding method");
+                    continue;
+                }
+                mInjectionMap.put(
+                        fragmentName, new FragmentInstantiationInfo(method, daggerComponent));
             }
         }
     }
@@ -134,9 +144,6 @@
          * Inject a QSFragment.
          */
         QSFragment createQSFragment();
-
-        /** Inject a CollapsedStatusBarFragment. */
-        CollapsedStatusBarFragment createCollapsedStatusBarFragment();
     }
 
     private class FragmentHostState {
@@ -161,4 +168,16 @@
             mFragmentHostManager.onConfigurationChanged(newConfig);
         }
     }
+
+    /** An object containing the information needed to instantiate a fragment. */
+    static class FragmentInstantiationInfo {
+        /** The method that returns a newly-created fragment of the given class. */
+        final Method mMethod;
+        /** The Dagger component that the method should be invoked on. */
+        final Object mDaggerComponent;
+        FragmentInstantiationInfo(Method method, Object daggerComponent) {
+            this.mMethod = method;
+            this.mDaggerComponent = daggerComponent;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 2f7c8ba..ff14064 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -31,8 +31,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.Dialog;
@@ -56,6 +54,7 @@
 import android.graphics.drawable.Drawable;
 import android.media.AudioManager;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
@@ -80,8 +79,6 @@
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.Window;
-import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -112,7 +109,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.MultiListLayout;
 import com.android.systemui.MultiListLayout.MultiListAdapter;
-import com.android.systemui.animation.Interpolators;
+import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dagger.qualifiers.Background;
@@ -123,6 +120,7 @@
 import com.android.systemui.scrim.ScrimDrawable;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.telephony.TelephonyListenerManager;
@@ -239,6 +237,7 @@
     private int mSmallestScreenWidthDp;
     private final Optional<StatusBar> mStatusBarOptional;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    private final DialogLaunchAnimator mDialogLaunchAnimator;
 
     @VisibleForTesting
     public enum GlobalActionsEvent implements UiEventLogger.UiEventEnum {
@@ -346,7 +345,8 @@
             @Main Handler handler,
             PackageManager packageManager,
             Optional<StatusBar> statusBarOptional,
-            KeyguardUpdateMonitor keyguardUpdateMonitor) {
+            KeyguardUpdateMonitor keyguardUpdateMonitor,
+            DialogLaunchAnimator dialogLaunchAnimator) {
         mContext = context;
         mWindowManagerFuncs = windowManagerFuncs;
         mAudioManager = audioManager;
@@ -377,6 +377,7 @@
         mSmallestScreenWidthDp = resources.getConfiguration().smallestScreenWidthDp;
         mStatusBarOptional = statusBarOptional;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mDialogLaunchAnimator = dialogLaunchAnimator;
 
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
@@ -435,11 +436,14 @@
     }
 
     /**
-     * Show the global actions dialog (creating if necessary)
+     * Show the global actions dialog (creating if necessary) or hide it if it's already showing.
      *
-     * @param keyguardShowing True if keyguard is showing
+     * @param keyguardShowing     True if keyguard is showing
+     * @param isDeviceProvisioned True if device is provisioned
+     * @param view                The view from which we should animate the dialog when showing it
      */
-    public void showOrHideDialog(boolean keyguardShowing, boolean isDeviceProvisioned) {
+    public void showOrHideDialog(boolean keyguardShowing, boolean isDeviceProvisioned,
+            @Nullable View view) {
         mKeyguardShowing = keyguardShowing;
         mDeviceProvisioned = isDeviceProvisioned;
         if (mDialog != null && mDialog.isShowing()) {
@@ -451,7 +455,7 @@
             mDialog.dismiss();
             mDialog = null;
         } else {
-            handleShow();
+            handleShow(view);
         }
     }
 
@@ -483,7 +487,7 @@
         }
     }
 
-    protected void handleShow() {
+    protected void handleShow(@Nullable View view) {
         awakenIfNecessary();
         mDialog = createDialog();
         prepareDialog();
@@ -493,8 +497,13 @@
         attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
         mDialog.getWindow().setAttributes(attrs);
         // Don't acquire soft keyboard focus, to avoid destroying state when capturing bugreports
-        mDialog.getWindow().setFlags(FLAG_ALT_FOCUSABLE_IM, FLAG_ALT_FOCUSABLE_IM);
-        mDialog.show();
+        mDialog.getWindow().addFlags(FLAG_ALT_FOCUSABLE_IM);
+
+        if (view != null) {
+            mDialogLaunchAnimator.showFromView(mDialog, view);
+        } else {
+            mDialog.show();
+        }
         mWindowManagerFuncs.onGlobalActionsShown();
     }
 
@@ -643,7 +652,7 @@
         }
     }
 
-    protected void onRotate() {
+    protected void onRefresh() {
         // re-allocate actions between main and overflow lists
         this.createActionItems();
     }
@@ -667,7 +676,7 @@
                 com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActionsLite,
                 mAdapter, mOverflowAdapter, mSysuiColorExtractor,
                 mStatusBarService, mNotificationShadeWindowController,
-                mSysUiState, this::onRotate, mKeyguardShowing, mPowerAdapter, mUiEventLogger,
+                mSysUiState, this::onRefresh, mKeyguardShowing, mPowerAdapter, mUiEventLogger,
                 mStatusBarOptional, mKeyguardUpdateMonitor, mLockPatternUtils);
 
         dialog.setOnDismissListener(this);
@@ -702,14 +711,6 @@
     }
 
     @Override
-    public void onUiModeChanged() {
-        mContext.getTheme().applyStyle(mContext.getThemeResId(), true);
-        if (mDialog != null && mDialog.isShowing()) {
-            mDialog.refreshDialog();
-        }
-    }
-
-    @Override
     public void onConfigChanged(Configuration newConfig) {
         if (mDialog != null && mDialog.isShowing()
                 && (newConfig.smallestScreenWidthDp != mSmallestScreenWidthDp)) {
@@ -717,6 +718,7 @@
             mDialog.refreshDialog();
         }
     }
+
     /**
      * Implements {@link GlobalActionsPanelPlugin.Callbacks#dismissGlobalActionsMenu()}, which is
      * called when the quick access wallet requests dismissal.
@@ -1363,6 +1365,10 @@
             final Action action = mAdapter.getItem(position);
             if (action instanceof LongPressAction) {
                 if (mDialog != null) {
+                    // Usually clicking an item shuts down the phone, locks, or starts an activity.
+                    // We don't want to animate back into the power button when that happens, so we
+                    // disable the dialog animation before dismissing.
+                    mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
                     mDialog.dismiss();
                 } else {
                     Log.w(TAG, "Action long-clicked while mDialog is null.");
@@ -1379,6 +1385,10 @@
                 if (mDialog != null) {
                     // don't dismiss the dialog if we're opening the power options menu
                     if (!(item instanceof PowerOptionsAction)) {
+                        // Usually clicking an item shuts down the phone, locks, or starts an
+                        // activity. We don't want to animate back into the power button when that
+                        // happens, so we disable the dialog animation before dismissing.
+                        mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
                         mDialog.dismiss();
                     }
                 } else {
@@ -1446,6 +1456,10 @@
             final Action action = getItem(position);
             if (action instanceof LongPressAction) {
                 if (mDialog != null) {
+                    // Usually clicking an item shuts down the phone, locks, or starts an activity.
+                    // We don't want to animate back into the power button when that happens, so we
+                    // disable the dialog animation before dismissing.
+                    mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
                     mDialog.dismiss();
                 } else {
                     Log.w(TAG, "Action long-clicked while mDialog is null.");
@@ -1459,6 +1473,10 @@
             Action item = getItem(position);
             if (!(item instanceof SilentModeTriStateAction)) {
                 if (mDialog != null) {
+                    // Usually clicking an item shuts down the phone, locks, or starts an activity.
+                    // We don't want to animate back into the power button when that happens, so we
+                    // disable the dialog animation before dismissing.
+                    mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
                     mDialog.dismiss();
                 } else {
                     Log.w(TAG, "Action clicked while mDialog is null.");
@@ -1510,6 +1528,10 @@
             final Action action = getItem(position);
             if (action instanceof LongPressAction) {
                 if (mDialog != null) {
+                    // Usually clicking an item shuts down the phone, locks, or starts an activity.
+                    // We don't want to animate back into the power button when that happens, so we
+                    // disable the dialog animation before dismissing.
+                    mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
                     mDialog.dismiss();
                 } else {
                     Log.w(TAG, "Action long-clicked while mDialog is null.");
@@ -1523,6 +1545,10 @@
             Action item = getItem(position);
             if (!(item instanceof SilentModeTriStateAction)) {
                 if (mDialog != null) {
+                    // Usually clicking an item shuts down the phone, locks, or starts an activity.
+                    // We don't want to animate back into the power button when that happens, so we
+                    // disable the dialog animation before dismissing.
+                    mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
                     mDialog.dismiss();
                 } else {
                     Log.w(TAG, "Action clicked while mDialog is null.");
@@ -2066,7 +2092,9 @@
                 case MESSAGE_DISMISS:
                     if (mDialog != null) {
                         if (SYSTEM_DIALOG_REASON_DREAM.equals(msg.obj)) {
-                            mDialog.completeDismiss();
+                            // Hide instantly.
+                            mDialog.hide();
+                            mDialog.dismiss();
                         } else {
                             mDialog.dismiss();
                         }
@@ -2113,7 +2141,7 @@
     }
 
     @VisibleForTesting
-    static class ActionsDialogLite extends Dialog implements DialogInterface,
+    static class ActionsDialogLite extends SystemUIDialog implements DialogInterface,
             ColorExtractor.OnColorsChangedListener {
 
         protected final Context mContext;
@@ -2126,13 +2154,12 @@
         protected Drawable mBackgroundDrawable;
         protected final SysuiColorExtractor mColorExtractor;
         private boolean mKeyguardShowing;
-        protected boolean mShowing;
         protected float mScrimAlpha;
         protected final NotificationShadeWindowController mNotificationShadeWindowController;
         protected final SysUiState mSysUiState;
         private ListPopupWindow mOverflowPopup;
         private Dialog mPowerOptionsDialog;
-        protected final Runnable mOnRotateCallback;
+        protected final Runnable mOnRefreshCallback;
         private UiEventLogger mUiEventLogger;
         private GestureDetector mGestureDetector;
         private Optional<StatusBar> mStatusBarOptional;
@@ -2151,7 +2178,7 @@
                     }
 
                     @Override
-                    public boolean onSingleTapConfirmed(MotionEvent e) {
+                    public boolean onSingleTapUp(MotionEvent e) {
                         // Close without opening shade
                         mUiEventLogger.log(GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE);
                         cancel();
@@ -2189,11 +2216,13 @@
                 MyOverflowAdapter overflowAdapter,
                 SysuiColorExtractor sysuiColorExtractor, IStatusBarService statusBarService,
                 NotificationShadeWindowController notificationShadeWindowController,
-                SysUiState sysuiState, Runnable onRotateCallback, boolean keyguardShowing,
+                SysUiState sysuiState, Runnable onRefreshCallback, boolean keyguardShowing,
                 MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger,
                 Optional<StatusBar> statusBarOptional,
                 KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils) {
-            super(context, themeRes);
+            // We set dismissOnDeviceLock to false because we have a custom broadcast receiver to
+            // dismiss this dialog when the device is locked.
+            super(context, themeRes, false /* dismissOnDeviceLock */);
             mContext = context;
             mAdapter = adapter;
             mOverflowAdapter = overflowAdapter;
@@ -2202,36 +2231,32 @@
             mStatusBarService = statusBarService;
             mNotificationShadeWindowController = notificationShadeWindowController;
             mSysUiState = sysuiState;
-            mOnRotateCallback = onRotateCallback;
+            mOnRefreshCallback = onRefreshCallback;
             mKeyguardShowing = keyguardShowing;
             mUiEventLogger = uiEventLogger;
             mStatusBarOptional = statusBarOptional;
             mKeyguardUpdateMonitor = keyguardUpdateMonitor;
             mLockPatternUtils = lockPatternUtils;
-
             mGestureDetector = new GestureDetector(mContext, mGestureListener);
+        }
 
-            // Window initialization
-            Window window = getWindow();
-            window.requestFeature(Window.FEATURE_NO_TITLE);
-            // Inflate the decor view, so the attributes below are not overwritten by the theme.
-            window.getDecorView();
-            window.getAttributes().systemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_STABLE
-                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
-            window.setLayout(MATCH_PARENT, MATCH_PARENT);
-            window.addFlags(
-                    WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                            | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
-                            | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
-                            | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
-            window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
-            window.getAttributes().setFitInsetsTypes(0 /* types */);
-            setTitle(R.string.global_actions);
-
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
             initializeLayout();
         }
 
         @Override
+        protected int getWidth() {
+            return MATCH_PARENT;
+        }
+
+        @Override
+        protected int getHeight() {
+            return MATCH_PARENT;
+        }
+
+        @Override
         public boolean onTouchEvent(MotionEvent event) {
             return mGestureDetector.onTouchEvent(event) || super.onTouchEvent(event);
         }
@@ -2371,7 +2396,8 @@
                             message.animate()
                                     .alpha(0f)
                                     .setDuration(TOAST_FADE_TIME)
-                                    .setStartDelay(visibleTime);
+                                    .setStartDelay(visibleTime)
+                                    .setListener(null);
                         }
                     });
         }
@@ -2423,122 +2449,32 @@
         @Override
         public void show() {
             super.show();
-            // split this up so we can override but still call Dialog.show
-            showDialog();
-        }
-
-        protected void showDialog() {
-            mShowing = true;
             mNotificationShadeWindowController.setRequestTopUi(true, TAG);
             mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, true)
                     .commitUpdate(mContext.getDisplayId());
-
-            ViewGroup root = (ViewGroup) mGlobalActionsLayout.getRootView();
-            root.setOnApplyWindowInsetsListener((v, windowInsets) -> {
-                root.setPadding(windowInsets.getStableInsetLeft(),
-                        windowInsets.getStableInsetTop(),
-                        windowInsets.getStableInsetRight(),
-                        windowInsets.getStableInsetBottom());
-                return WindowInsets.CONSUMED;
-            });
-
-            mBackgroundDrawable.setAlpha(0);
-            float xOffset = mGlobalActionsLayout.getAnimationOffsetX();
-            ObjectAnimator alphaAnimator =
-                    ObjectAnimator.ofFloat(mContainer, "alpha", 0f, 1f);
-            alphaAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-            alphaAnimator.setDuration(183);
-            alphaAnimator.addUpdateListener((animation) -> {
-                float animatedValue = animation.getAnimatedFraction();
-                int alpha = (int) (animatedValue * mScrimAlpha * 255);
-                mBackgroundDrawable.setAlpha(alpha);
-            });
-
-            ObjectAnimator xAnimator =
-                    ObjectAnimator.ofFloat(mContainer, "translationX", xOffset, 0f);
-            xAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
-            xAnimator.setDuration(350);
-
-            AnimatorSet animatorSet = new AnimatorSet();
-            animatorSet.playTogether(alphaAnimator, xAnimator);
-            animatorSet.start();
         }
 
         @Override
         public void dismiss() {
-            dismissWithAnimation(() -> {
-                dismissInternal();
-            });
-        }
+            dismissOverflow();
+            dismissPowerOptions();
 
-        protected void dismissInternal() {
-            mContainer.setTranslationX(0);
-            ObjectAnimator alphaAnimator =
-                    ObjectAnimator.ofFloat(mContainer, "alpha", 1f, 0f);
-            alphaAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
-            alphaAnimator.setDuration(233);
-            alphaAnimator.addUpdateListener((animation) -> {
-                float animatedValue = 1f - animation.getAnimatedFraction();
-                int alpha = (int) (animatedValue * mScrimAlpha * 255);
-                mBackgroundDrawable.setAlpha(alpha);
-            });
-
-            float xOffset = mGlobalActionsLayout.getAnimationOffsetX();
-            ObjectAnimator xAnimator =
-                    ObjectAnimator.ofFloat(mContainer, "translationX", 0f, xOffset);
-            xAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN);
-            xAnimator.setDuration(350);
-
-            AnimatorSet animatorSet = new AnimatorSet();
-            animatorSet.playTogether(alphaAnimator, xAnimator);
-            animatorSet.addListener(new AnimatorListenerAdapter() {
-                public void onAnimationEnd(Animator animation) {
-                    completeDismiss();
-                }
-            });
-
-            animatorSet.start();
-
-            // close first, as popup windows will not fade during the animation
-            dismissOverflow(false);
-            dismissPowerOptions(false);
-        }
-
-        void dismissWithAnimation(Runnable animation) {
-            if (!mShowing) {
-                return;
-            }
-            mShowing = false;
-            animation.run();
-        }
-
-        protected void completeDismiss() {
-            mShowing = false;
-            dismissOverflow(true);
-            dismissPowerOptions(true);
             mNotificationShadeWindowController.setRequestTopUi(false, TAG);
             mSysUiState.setFlag(SYSUI_STATE_GLOBAL_ACTIONS_SHOWING, false)
                     .commitUpdate(mContext.getDisplayId());
+
             super.dismiss();
         }
 
-        protected final void dismissOverflow(boolean immediate) {
+        protected final void dismissOverflow() {
             if (mOverflowPopup != null) {
-                if (immediate) {
-                    mOverflowPopup.dismissImmediate();
-                } else {
-                    mOverflowPopup.dismiss();
-                }
+                mOverflowPopup.dismiss();
             }
         }
 
-        protected final void dismissPowerOptions(boolean immediate) {
+        protected final void dismissPowerOptions() {
             if (mPowerOptionsDialog != null) {
-                if (immediate) {
-                    mPowerOptionsDialog.dismiss();
-                } else {
-                    mPowerOptionsDialog.dismiss();
-                }
+                mPowerOptionsDialog.dismiss();
             }
         }
 
@@ -2574,20 +2510,18 @@
         }
 
         public void refreshDialog() {
-            // ensure dropdown menus are dismissed before re-initializing the dialog
-            dismissOverflow(true);
-            dismissPowerOptions(true);
+            mOnRefreshCallback.run();
 
-            // re-create dialog
-            initializeLayout();
+            // Dismiss the dropdown menus.
+            dismissOverflow();
+            dismissPowerOptions();
+
+            // Update the list as the max number of items per row has probably changed.
             mGlobalActionsLayout.updateList();
         }
 
         public void onRotate(int from, int to) {
-            if (mShowing) {
-                mOnRotateCallback.run();
-                refreshDialog();
-            }
+            refreshDialog();
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index c4508e0..96ae646 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -82,7 +82,7 @@
         if (mDisabled) return;
         mGlobalActionsDialog = mGlobalActionsDialogLazy.get();
         mGlobalActionsDialog.showOrHideDialog(mKeyguardStateController.isShowing(),
-                mDeviceProvisionedController.isDeviceProvisioned());
+                mDeviceProvisionedController.isDeviceProvisioned(), null /* view */);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index a6455e6..a801647 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.animation.Interpolators
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.shared.system.smartspace.SmartspaceTransitionController
 import com.android.systemui.statusbar.policy.KeyguardStateController
 import dagger.Lazy
@@ -354,7 +355,7 @@
      * keyguard visible.
      */
     private fun updateKeyguardViewMediatorIfThresholdsReached() {
-        if (!featureFlags.isNewKeyguardSwipeAnimationEnabled) {
+        if (!featureFlags.isEnabled(Flags.NEW_UNLOCK_SWIPE_ANIMATION)) {
             return
         }
 
@@ -410,7 +411,7 @@
      * know if it needs to do something as a result.
      */
     private fun updateSmartSpaceTransition() {
-        if (!featureFlags.isSmartSpaceSharedElementTransitionEnabled) {
+        if (!featureFlags.isEnabled(Flags.SMARTSPACE_SHARED_ELEMENT_TRANSITION_ENABLED)) {
             return
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index e97e762..fbc9ba6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -793,7 +793,8 @@
                 return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
             } else if (trust && (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) {
                 return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
-            } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0) {
+            } else if (any && ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0
+                    || mUpdateMonitor.isFingerprintLockedOut())) {
                 return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
             } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) != 0) {
                 return KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE;
@@ -820,6 +821,7 @@
 
     private final KeyguardStateController mKeyguardStateController;
     private final Lazy<KeyguardUnlockAnimationController> mKeyguardUnlockAnimationControllerLazy;
+    private final InteractionJankMonitor mInteractionJankMonitor;
     private boolean mWallpaperSupportsAmbientMode;
 
     /**
@@ -845,7 +847,8 @@
             KeyguardStateController keyguardStateController,
             Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationControllerLazy,
             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
-            Lazy<NotificationShadeDepthController> notificationShadeDepthController) {
+            Lazy<NotificationShadeDepthController> notificationShadeDepthController,
+            InteractionJankMonitor interactionJankMonitor) {
         super(context);
         mFalsingCollector = falsingCollector;
         mLockPatternUtils = lockPatternUtils;
@@ -882,6 +885,7 @@
         mKeyguardStateController = keyguardStateController;
         mKeyguardUnlockAnimationControllerLazy = keyguardUnlockAnimationControllerLazy;
         mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+        mInteractionJankMonitor = interactionJankMonitor;
     }
 
     public void userActivity() {
@@ -2245,8 +2249,7 @@
                                 onKeyguardExitFinished();
                                 mKeyguardViewControllerLazy.get().hide(0 /* startTime */,
                                         0 /* fadeoutDuration */);
-                                InteractionJankMonitor.getInstance()
-                                        .end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
+                                mInteractionJankMonitor.end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
                             }
 
                             @Override
@@ -2255,7 +2258,7 @@
                             }
                         };
                 try {
-                    InteractionJankMonitor.getInstance().begin(
+                    mInteractionJankMonitor.begin(
                             createInteractionJankMonitorConf("RunRemoteAnimation"));
                     runner.onAnimationStart(WindowManager.TRANSIT_KEYGUARD_GOING_AWAY, apps,
                             wallpapers, nonApps, callback);
@@ -2271,14 +2274,14 @@
                 mSurfaceBehindRemoteAnimationFinishedCallback = finishedCallback;
                 mSurfaceBehindRemoteAnimationRunning = true;
 
-                InteractionJankMonitor.getInstance().begin(
+                mInteractionJankMonitor.begin(
                         createInteractionJankMonitorConf("DismissPanel"));
 
                 // Pass the surface and metadata to the unlock animation controller.
                 mKeyguardUnlockAnimationControllerLazy.get().notifyStartKeyguardExitAnimation(
                         apps[0], startTime, mSurfaceBehindRemoteAnimationRequested);
             } else {
-                InteractionJankMonitor.getInstance().begin(
+                mInteractionJankMonitor.begin(
                         createInteractionJankMonitorConf("RemoteAnimationDisabled"));
 
                 mKeyguardViewControllerLazy.get().hide(startTime, fadeoutDuration);
@@ -2288,7 +2291,7 @@
                 // supported, so it's always null.
                 mContext.getMainExecutor().execute(() -> {
                     if (finishedCallback == null) {
-                        InteractionJankMonitor.getInstance().end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
+                        mInteractionJankMonitor.end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
                         return;
                     }
 
@@ -2316,8 +2319,7 @@
                             } catch (RemoteException e) {
                                 Slog.e(TAG, "RemoteException");
                             } finally {
-                                InteractionJankMonitor.getInstance()
-                                        .end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
+                                mInteractionJankMonitor.end(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
                             }
                         }
 
@@ -2328,8 +2330,7 @@
                             } catch (RemoteException e) {
                                 Slog.e(TAG, "RemoteException");
                             } finally {
-                                InteractionJankMonitor.getInstance()
-                                        .cancel(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
+                                mInteractionJankMonitor.cancel(CUJ_LOCKSCREEN_UNLOCK_ANIMATION);
                             }
                         }
                     });
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 cae9fee..8d23e9f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -22,6 +22,7 @@
 import android.content.pm.PackageManager;
 import android.os.PowerManager;
 
+import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardDisplayManager;
 import com.android.keyguard.KeyguardUpdateMonitor;
@@ -97,7 +98,8 @@
             KeyguardStateController keyguardStateController,
             Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationController,
             UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
-            Lazy<NotificationShadeDepthController> notificationShadeDepthController) {
+            Lazy<NotificationShadeDepthController> notificationShadeDepthController,
+            InteractionJankMonitor interactionJankMonitor) {
         return new KeyguardViewMediator(
                 context,
                 falsingCollector,
@@ -120,7 +122,8 @@
                 keyguardStateController,
                 keyguardUnlockAnimationController,
                 unlockedScreenOffAnimationController,
-                notificationShadeDepthController
+                notificationShadeDepthController,
+                interactionJankMonitor
         );
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt b/packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
index 0622df3..5296ee6 100644
--- a/packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/log/LogBufferFactory.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.log
 
+import android.app.ActivityManager
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dump.DumpManager
 import javax.inject.Inject
@@ -25,9 +26,18 @@
     private val dumpManager: DumpManager,
     private val logcatEchoTracker: LogcatEchoTracker
 ) {
+    /* limit the size of maxPoolSize for low ram (Go) devices */
+    private fun poolLimit(maxPoolSize_requested: Int): Int {
+        if (ActivityManager.isLowRamDeviceStatic()) {
+            return minOf(maxPoolSize_requested, 20) /* low ram max log size*/
+        } else {
+            return maxPoolSize_requested
+        }
+    }
+
     @JvmOverloads
     fun create(name: String, maxPoolSize: Int, flexSize: Int = 10): LogBuffer {
-        val buffer = LogBuffer(name, maxPoolSize, flexSize, logcatEchoTracker)
+        val buffer = LogBuffer(name, poolLimit(maxPoolSize), flexSize, logcatEchoTracker)
         dumpManager.registerBuffer(name, buffer)
         return buffer
     }
diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java
index c8afd72..9ca0293 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/CollapsedSbFragmentLog.java
@@ -26,8 +26,8 @@
 import javax.inject.Qualifier;
 
 /**
- * A {@link LogBuffer} for
- * {@link com.android.systemui.statusbar.phone.CollapsedStatusBarFragment}-related messages.
+ * A {@link LogBuffer} for {@link
+ * com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment}-related messages.
  */
 @Qualifier
 @Documented
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 02beff9..d3bd0a5 100644
--- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
+++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java
@@ -110,7 +110,7 @@
 
     /**
      * Provides a logging buffer for
-     * {@link com.android.systemui.statusbar.phone.CollapsedStatusBarFragment}.
+     * {@link com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment}.
      */
     @Provides
     @SysUISingleton
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index e87558e..d54b151 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -400,7 +400,7 @@
         }
         updatePageIndicator()
         mediaCarouselScrollHandler.onPlayersChanged()
-        mediaCarousel.requiresRemeasuring = true
+        mediaFrame.requiresRemeasuring = true
         // Check postcondition: mediaContent should have the same number of children as there are
         // elements in mediaPlayers.
         if (MediaPlayerData.players().size != mediaContent.childCount) {
@@ -439,7 +439,7 @@
         updatePlayerToState(newRecs, noAnimation = true)
         reorderAllPlayers(curVisibleMediaKey)
         updatePageIndicator()
-        mediaCarousel.requiresRemeasuring = true
+        mediaFrame.requiresRemeasuring = true
         // Check postcondition: mediaContent should have the same number of children as there are
         // elements in mediaPlayers.
         if (MediaPlayerData.players().size != mediaContent.childCount) {
@@ -833,12 +833,15 @@
     )
 
     private val comparator =
-            compareByDescending<MediaSortKey> { it.data.isPlaying == true && it.data.isLocalSession }
-                    .thenByDescending { it.data.isPlaying }
-                    .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec }
-                    .thenByDescending { !it.data.resumption }
-                    .thenByDescending { it.updateTime }
-                    .thenByDescending { !it.data.isLocalSession }
+            compareByDescending<MediaSortKey> { it.data.isPlaying == true &&
+                        it.data.playbackLocation == MediaData.PLAYBACK_LOCAL }
+                .thenByDescending { it.data.isPlaying == true &&
+                        it.data.playbackLocation == MediaData.PLAYBACK_CAST_LOCAL }
+                .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec }
+                .thenByDescending { !it.data.resumption }
+                .thenByDescending { it.data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE }
+                .thenByDescending { it.updateTime }
+                .thenByDescending { it.data.notificationKey }
 
     private val mediaPlayers = TreeMap<MediaSortKey, MediaControlPanel>(comparator)
     private val mediaData: MutableMap<String, MediaSortKey> = mutableMapOf()
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
index 6f0c887..bda07f4 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
@@ -82,9 +82,9 @@
      */
     var resumeAction: Runnable?,
     /**
-     * Local or remote playback
+     * Playback location: one of PLAYBACK_LOCAL, PLAYBACK_CAST_LOCAL, or PLAYBACK_CAST_REMOTE
      */
-    var isLocalSession: Boolean = true,
+    var playbackLocation: Int = PLAYBACK_LOCAL,
     /**
      * Indicates that this player is a resumption player (ie. It only shows a play actions which
      * will start the app and start playing).
@@ -110,7 +110,20 @@
      * Timestamp when this player was last active.
      */
     var lastActive: Long = 0L
-)
+) {
+    companion object {
+        /** Media is playing on the local device */
+        const val PLAYBACK_LOCAL = 0
+        /** Media is cast but originated on the local device */
+        const val PLAYBACK_CAST_LOCAL = 1
+        /** Media is from a remote cast notification */
+        const val PLAYBACK_CAST_REMOTE = 2
+    }
+
+    fun isLocalSession(): Boolean {
+        return playbackLocation == PLAYBACK_LOCAL
+    }
+}
 
 /** State of a media action. */
 data class MediaAction(
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 3631d2f..6e86bef 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -27,6 +27,8 @@
 import android.content.Context
 import android.content.Intent
 import android.content.IntentFilter
+import android.content.pm.ApplicationInfo
+import android.content.pm.PackageManager
 import android.graphics.Bitmap
 import android.graphics.Canvas
 import android.graphics.ImageDecoder
@@ -85,15 +87,7 @@
     "INVALID", null, emptyList(), null, 0)
 
 fun isMediaNotification(sbn: StatusBarNotification): Boolean {
-    if (!sbn.notification.hasMediaSession()) {
-        return false
-    }
-    val notificationStyle = sbn.notification.notificationStyle
-    if (Notification.DecoratedMediaCustomViewStyle::class.java.equals(notificationStyle) ||
-            Notification.MediaStyle::class.java.equals(notificationStyle)) {
-        return true
-    }
-    return false
+    return sbn.notification.isMediaNotification()
 }
 
 /**
@@ -153,6 +147,24 @@
     private var smartspaceSession: SmartspaceSession? = null
     private var allowMediaRecommendations = Utils.allowMediaRecommendations(context)
 
+    /**
+     * Check whether this notification is an RCN
+     * TODO(b/204910409) implement new API for explicitly declaring this
+     */
+    private fun isRemoteCastNotification(sbn: StatusBarNotification): Boolean {
+        val pm = context.packageManager
+        try {
+            val info = pm.getApplicationInfo(sbn.packageName, PackageManager.MATCH_SYSTEM_ONLY)
+            if (info.privateFlags and ApplicationInfo.PRIVATE_FLAG_PRIVILEGED != 0) {
+                val extras = sbn.notification.extras
+                if (extras.containsKey(Notification.EXTRA_SUBSTITUTE_APP_NAME)) {
+                    return true
+                }
+            }
+        } catch (e: PackageManager.NameNotFoundException) { }
+        return false
+    }
+
     @Inject
     constructor(
         context: Context,
@@ -442,7 +454,7 @@
         val existed = mediaEntries[key] != null
         backgroundExecutor.execute {
             mediaEntries[key]?.let { mediaData ->
-                if (mediaData.isLocalSession) {
+                if (mediaData.isLocalSession()) {
                     mediaData.token?.let {
                         val mediaController = mediaControllerFactory.create(it)
                         mediaController.transportControls.stop()
@@ -626,8 +638,11 @@
             }
         }
 
-        val isLocalSession = mediaController.playbackInfo?.playbackType ==
-            MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL
+        val playbackLocation =
+                if (isRemoteCastNotification(sbn)) MediaData.PLAYBACK_CAST_REMOTE
+                else if (mediaController.playbackInfo?.playbackType ==
+                    MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL) MediaData.PLAYBACK_LOCAL
+                else MediaData.PLAYBACK_CAST_LOCAL
         val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null
         val lastActive = systemClock.elapsedRealtime()
         foregroundExecutor.execute {
@@ -637,7 +652,7 @@
             onMediaDataLoaded(key, oldKey, MediaData(sbn.normalizedUserId, true, bgColor, app,
                     smallIcon, artist, song, artWorkIcon, actionIcons,
                     actionsToShowCollapsed, sbn.packageName, token, notif.contentIntent, null,
-                    active, resumeAction = resumeAction, isLocalSession = isLocalSession,
+                    active, resumeAction = resumeAction, playbackLocation = playbackLocation,
                     notificationKey = key, hasCheckedForResume = hasCheckedForResume,
                     isPlaying = isPlaying, isClearable = sbn.isClearable(),
                     lastActive = lastActive))
@@ -762,7 +777,7 @@
     fun onNotificationRemoved(key: String) {
         Assert.isMainThread()
         val removed = mediaEntries.remove(key)
-        if (useMediaResumption && removed?.resumeAction != null && removed?.isLocalSession) {
+        if (useMediaResumption && removed?.resumeAction != null && removed?.isLocalSession()) {
             Log.d(TAG, "Not removing $key because resumable")
             // Move to resume key (aka package name) if that key doesn't already exist.
             val resumeAction = getResumeMediaAction(removed.resumeAction!!)
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
index 608c784..d8095f3 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
@@ -193,7 +193,7 @@
                 mediaBrowser = null
             }
             // If we don't have a resume action, check if we haven't already
-            if (data.resumeAction == null && !data.hasCheckedForResume && data.isLocalSession) {
+            if (data.resumeAction == null && !data.hasCheckedForResume && data.isLocalSession()) {
                 // TODO also check for a media button receiver intended for restarting (b/154127084)
                 Log.d(TAG, "Checking for service component for " + data.packageName)
                 val pm = context.packageManager
diff --git a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
index 57ac9df..237d077 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
@@ -16,11 +16,19 @@
 
 package com.android.systemui.media.dagger;
 
+import android.content.Context;
+import android.view.WindowManager;
+
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.media.MediaDataManager;
 import com.android.systemui.media.MediaHierarchyManager;
 import com.android.systemui.media.MediaHost;
 import com.android.systemui.media.MediaHostStatesManager;
+import com.android.systemui.media.taptotransfer.MediaTttChipController;
+import com.android.systemui.media.taptotransfer.MediaTttFlags;
+import com.android.systemui.statusbar.commandline.CommandRegistry;
+
+import java.util.Optional;
 
 import javax.inject.Named;
 
@@ -63,4 +71,18 @@
             MediaHostStatesManager statesManager) {
         return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager);
     }
+
+    /** */
+    @Provides
+    @SysUISingleton
+    static Optional<MediaTttChipController> providesMediaTttChipController(
+            MediaTttFlags mediaTttFlags,
+            Context context,
+            CommandRegistry commandRegistry,
+            WindowManager windowManager) {
+        if (!mediaTttFlags.isMediaTttEnabled()) {
+            return Optional.empty();
+        }
+        return Optional.of(new MediaTttChipController(context, commandRegistry, windowManager));
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 113ba59..5fa66cd 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -40,6 +40,8 @@
 
     private static final String TAG = "MediaOutputAdapter";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final float DEVICE_DISCONNECTED_ALPHA = 0.5f;
+    private static final float DEVICE_CONNECTED_ALPHA = 1f;
 
     private final MediaOutputDialog mMediaOutputDialog;
     private ViewGroup mConnectedItem;
@@ -109,8 +111,8 @@
             if (currentlyConnected) {
                 mConnectedItem = mContainerLayout;
             }
-            mBottomDivider.setVisibility(View.GONE);
             mCheckBox.setVisibility(View.GONE);
+            mStatusIcon.setVisibility(View.GONE);
             if (currentlyConnected && mController.isActiveRemoteDevice(device)
                     && mController.getSelectableMediaDevice().size() > 0) {
                 // Init active device layout
@@ -124,35 +126,42 @@
             if (mCurrentActivePosition == position) {
                 mCurrentActivePosition = -1;
             }
+            if (device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
+                    && !device.isConnected()) {
+                mTitleText.setAlpha(DEVICE_DISCONNECTED_ALPHA);
+                mTitleIcon.setAlpha(DEVICE_DISCONNECTED_ALPHA);
+            } else {
+                mTitleText.setAlpha(DEVICE_CONNECTED_ALPHA);
+                mTitleIcon.setAlpha(DEVICE_CONNECTED_ALPHA);
+            }
+
             if (mController.isTransferring()) {
                 if (device.getState() == MediaDeviceState.STATE_CONNECTING
                         && !mController.hasAdjustVolumeUserRestriction()) {
-                    setTwoLineLayout(device, true /* bFocused */, false /* showSeekBar*/,
-                            true /* showProgressBar */, false /* showSubtitle */);
+                    setSingleLineLayout(getItemTitle(device), true /* bFocused */,
+                            false /* showSeekBar*/,
+                            true /* showProgressBar */, false /* showStatus */);
                 } else {
                     setSingleLineLayout(getItemTitle(device), false /* bFocused */);
                 }
             } else {
                 // Set different layout for each device
                 if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
+                    mStatusIcon.setImageDrawable(
+                            mContext.getDrawable(R.drawable.media_output_status_failed));
                     setTwoLineLayout(device, false /* bFocused */,
                             false /* showSeekBar */, false /* showProgressBar */,
-                            true /* showSubtitle */);
+                            true /* showSubtitle */, true /* showStatus */);
                     mSubTitleText.setText(R.string.media_output_dialog_connect_failed);
                     mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
                 } else if (!mController.hasAdjustVolumeUserRestriction() && currentlyConnected) {
-                    setTwoLineLayout(device, true /* bFocused */, true /* showSeekBar */,
-                            false /* showProgressBar */, false /* showSubtitle */);
+                    mStatusIcon.setImageDrawable(
+                            mContext.getDrawable(R.drawable.media_output_status_check));
+                    setSingleLineLayout(getItemTitle(device), true /* bFocused */,
+                            true /* showSeekBar */,
+                            false /* showProgressBar */, true /* showStatus */);
                     initSeekbar(device);
                     mCurrentActivePosition = position;
-                } else if (
-                        device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
-                                && !device.isConnected()) {
-                    setTwoLineLayout(device, false /* bFocused */,
-                            false /* showSeekBar */, false /* showProgressBar */,
-                            true /* showSubtitle */);
-                    mSubTitleText.setText(R.string.media_output_dialog_disconnected);
-                    mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
                 } else {
                     setSingleLineLayout(getItemTitle(device), false /* bFocused */);
                     mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
@@ -165,7 +174,6 @@
             if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
                 mCheckBox.setVisibility(View.GONE);
                 mAddIcon.setVisibility(View.GONE);
-                mBottomDivider.setVisibility(View.GONE);
                 setSingleLineLayout(mContext.getText(R.string.media_output_dialog_pairing_new),
                         false /* bFocused */);
                 final Drawable d = mContext.getDrawable(R.drawable.ic_add);
@@ -175,7 +183,6 @@
                 mContainerLayout.setOnClickListener(v -> onItemClick(CUSTOMIZED_ITEM_PAIR_NEW));
             } else if (customizedItem == CUSTOMIZED_ITEM_DYNAMIC_GROUP) {
                 mConnectedItem = mContainerLayout;
-                mBottomDivider.setVisibility(View.GONE);
                 mCheckBox.setVisibility(View.GONE);
                 if (mController.getSelectableMediaDevice().size() > 0) {
                     mAddIcon.setVisibility(View.VISIBLE);
@@ -200,7 +207,6 @@
             }
 
             mCurrentActivePosition = -1;
-            playSwitchingAnim(mConnectedItem, view);
             mController.connectDevice(device);
             device.setState(MediaDeviceState.STATE_CONNECTING);
             if (!isAnimating()) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 868193b..dc4aaa9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -30,6 +30,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.CheckBox;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ProgressBar;
@@ -40,7 +41,6 @@
 import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.settingslib.bluetooth.BluetoothUtils;
 import com.android.settingslib.media.MediaDevice;
 import com.android.settingslib.utils.ThreadUtils;
 import com.android.systemui.R;
@@ -113,6 +113,7 @@
         private static final int ANIM_DURATION = 200;
 
         final LinearLayout mContainerLayout;
+        final FrameLayout mItemLayout;
         final TextView mTitleText;
         final TextView mTwoLineTitleText;
         final TextView mSubTitleText;
@@ -121,13 +122,14 @@
         final ProgressBar mProgressBar;
         final SeekBar mSeekBar;
         final RelativeLayout mTwoLineLayout;
-        final View mBottomDivider;
+        final ImageView mStatusIcon;
         final CheckBox mCheckBox;
         private String mDeviceId;
 
         MediaDeviceBaseViewHolder(View view) {
             super(view);
             mContainerLayout = view.requireViewById(R.id.device_container);
+            mItemLayout = view.requireViewById(R.id.item_layout);
             mTitleText = view.requireViewById(R.id.title);
             mSubTitleText = view.requireViewById(R.id.subtitle);
             mTwoLineLayout = view.requireViewById(R.id.two_line_layout);
@@ -135,8 +137,8 @@
             mTitleIcon = view.requireViewById(R.id.title_icon);
             mProgressBar = view.requireViewById(R.id.volume_indeterminate_progress);
             mSeekBar = view.requireViewById(R.id.volume_seekbar);
-            mBottomDivider = view.requireViewById(R.id.bottom_divider);
             mAddIcon = view.requireViewById(R.id.add_icon);
+            mStatusIcon = view.requireViewById(R.id.media_output_item_status);
             mCheckBox = view.requireViewById(R.id.check_box);
         }
 
@@ -156,11 +158,26 @@
         abstract void onBind(int customizedItem, boolean topMargin, boolean bottomMargin);
 
         void setSingleLineLayout(CharSequence title, boolean bFocused) {
+            setSingleLineLayout(title, bFocused, false, false, false);
+        }
+
+        void setSingleLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar,
+                boolean showProgressBar, boolean showStatus) {
             mTwoLineLayout.setVisibility(View.GONE);
-            mProgressBar.setVisibility(View.GONE);
+            final Drawable backgroundDrawable =
+                    showSeekBar
+                            ? mContext.getDrawable(R.drawable.media_output_item_background_active)
+                                    .mutate() : mContext.getDrawable(
+                            R.drawable.media_output_item_background)
+                            .mutate();
+            mItemLayout.setBackground(backgroundDrawable);
+            mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
+            mSeekBar.setAlpha(1);
+            mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
+            mStatusIcon.setVisibility(showStatus ? View.VISIBLE : View.GONE);
+            mTitleText.setText(title);
             mTitleText.setVisibility(View.VISIBLE);
             mTitleText.setTranslationY(0);
-            mTitleText.setText(title);
             if (bFocused) {
                 mTitleText.setTypeface(Typeface.create(mContext.getString(
                         com.android.internal.R.string.config_headlineFontFamilyMedium),
@@ -173,20 +190,32 @@
 
         void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
                 boolean showProgressBar, boolean showSubtitle) {
-            setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle);
+            setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle,
+                    false);
+        }
+
+        void setTwoLineLayout(MediaDevice device, boolean bFocused, boolean showSeekBar,
+                boolean showProgressBar, boolean showSubtitle, boolean showStatus) {
+            setTwoLineLayout(device, null, bFocused, showSeekBar, showProgressBar, showSubtitle,
+                    showStatus);
         }
 
         void setTwoLineLayout(CharSequence title, boolean bFocused, boolean showSeekBar,
                 boolean showProgressBar, boolean showSubtitle) {
-            setTwoLineLayout(null, title, bFocused, showSeekBar, showProgressBar, showSubtitle);
+            setTwoLineLayout(null, title, bFocused, showSeekBar, showProgressBar, showSubtitle,
+                    false);
         }
 
         private void setTwoLineLayout(MediaDevice device, CharSequence title, boolean bFocused,
-                boolean showSeekBar, boolean showProgressBar, boolean showSubtitle) {
+                boolean showSeekBar, boolean showProgressBar, boolean showSubtitle,
+                boolean showStatus) {
             mTitleText.setVisibility(View.GONE);
             mTwoLineLayout.setVisibility(View.VISIBLE);
+            mStatusIcon.setVisibility(showStatus ? View.VISIBLE : View.GONE);
             mSeekBar.setAlpha(1);
             mSeekBar.setVisibility(showSeekBar ? View.VISIBLE : View.GONE);
+            mItemLayout.setBackground(mContext.getDrawable(R.drawable.media_output_item_background)
+                    .mutate());
             mProgressBar.setVisibility(showProgressBar ? View.VISIBLE : View.GONE);
             mSubTitleText.setVisibility(showSubtitle ? View.VISIBLE : View.GONE);
             mTwoLineTitleText.setTranslationY(0);
@@ -289,6 +318,9 @@
                         public void onAnimationEnd(Animator animation) {
                             to.requireViewById(R.id.volume_indeterminate_progress).setVisibility(
                                     View.VISIBLE);
+                            // Unset the listener, otherwise this may persist for another view
+                            // property animation
+                            toTitleText.animate().setListener(null);
                         }
                     });
             // Animation for seek bar
@@ -312,8 +344,14 @@
                                         public void onAnimationEnd(Animator animation) {
                                             mIsAnimating = false;
                                             notifyDataSetChanged();
+                                            // Unset the listener, otherwise this may persist for
+                                            // another view property animation
+                                            fromTitleText.animate().setListener(null);
                                         }
                                     });
+                            // Unset the listener, otherwise this may persist for another view
+                            // property animation
+                            fromSeekBar.animate().setListener(null);
                         }
                     });
         }
@@ -325,7 +363,7 @@
                     R.color.advanced_icon_color, mContext.getTheme());
             drawable.setColorFilter(new PorterDuffColorFilter(list.getDefaultColor(),
                     PorterDuff.Mode.SRC_IN));
-            return BluetoothUtils.buildAdvancedDrawable(mContext, drawable);
+            return drawable;
         }
 
         private void disableSeekBar() {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 26ce645..91d0b49 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -20,6 +20,7 @@
 import static android.view.WindowInsets.Type.statusBars;
 
 import android.content.Context;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -64,6 +65,7 @@
     private TextView mHeaderTitle;
     private TextView mHeaderSubtitle;
     private ImageView mHeaderIcon;
+    private ImageView mAppResourceIcon;
     private RecyclerView mDevicesRecyclerView;
     private LinearLayout mDeviceListLayout;
     private Button mDoneButton;
@@ -112,6 +114,7 @@
         mDeviceListLayout = mDialogView.requireViewById(R.id.device_list);
         mDoneButton = mDialogView.requireViewById(R.id.done);
         mStopButton = mDialogView.requireViewById(R.id.stop);
+        mAppResourceIcon = mDialogView.requireViewById(R.id.app_source_icon);
 
         mDeviceListLayout.getViewTreeObserver().addOnGlobalLayoutListener(
                 mDeviceListLayoutListener);
@@ -145,6 +148,12 @@
         // Update header icon
         final int iconRes = getHeaderIconRes();
         final IconCompat iconCompat = getHeaderIcon();
+        final Drawable appSourceDrawable = getAppSourceIcon();
+        if (appSourceDrawable != null) {
+            mAppResourceIcon.setImageDrawable(appSourceDrawable);
+        } else {
+            mAppResourceIcon.setVisibility(View.GONE);
+        }
         if (iconRes != 0) {
             mHeaderIcon.setVisibility(View.VISIBLE);
             mHeaderIcon.setImageResource(iconRes);
@@ -183,6 +192,8 @@
         mStopButton.setVisibility(getStopButtonVisibility());
     }
 
+    abstract Drawable getAppSourceIcon();
+
     abstract int getHeaderIconRes();
 
     abstract IconCompat getHeaderIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index 1981269..eef5fb0 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -19,6 +19,7 @@
 import android.app.Notification;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
@@ -181,6 +182,20 @@
         mMetricLogger.logOutputFailure(mMediaDevices, reason);
     }
 
+    Drawable getAppSourceIcon() {
+        if (mPackageName.isEmpty()) {
+            return null;
+        }
+        try {
+            Log.d(TAG, "try to get app icon");
+            return mContext.getPackageManager()
+                    .getApplicationIcon(mPackageName);
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.d(TAG, "icon not found");
+            return null;
+        }
+    }
+
     CharSequence getHeaderTitle() {
         if (mMediaController != null) {
             final MediaMetadata metadata = mMediaController.getMetadata();
@@ -242,7 +257,7 @@
         for (NotificationEntry entry
                 : mNotificationEntryManager.getActiveNotificationsForCurrentUser()) {
             final Notification notification = entry.getSbn().getNotification();
-            if (notification.hasMediaSession()
+            if (notification.isMediaNotification()
                     && TextUtils.equals(entry.getSbn().getPackageName(), mPackageName)) {
                 final Icon icon = notification.getLargeIcon();
                 if (icon == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
index eca8ac9..7696a1f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
@@ -17,6 +17,7 @@
 package com.android.systemui.media.dialog;
 
 import android.content.Context;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.view.View;
 import android.view.WindowManager;
@@ -79,6 +80,11 @@
     }
 
     @Override
+    Drawable getAppSourceIcon() {
+        return mMediaOutputController.getAppSourceIcon();
+    }
+
+    @Override
     int getStopButtonVisibility() {
         return mMediaOutputController.isActiveRemoteDevice(
                 mMediaOutputController.getCurrentConnectedMediaDevice()) ? View.VISIBLE : View.GONE;
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
index a201c07..104ddf9 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
@@ -97,7 +97,6 @@
         void onBind(MediaDevice device, boolean topMargin, boolean bottomMargin, int position) {
             super.onBind(device, topMargin, bottomMargin, position);
             mAddIcon.setVisibility(View.GONE);
-            mBottomDivider.setVisibility(View.GONE);
             mCheckBox.setVisibility(View.VISIBLE);
             mCheckBox.setOnCheckedChangeListener((buttonView, isChecked) -> {
                 onCheckBoxClicked(isChecked, device);
@@ -131,7 +130,6 @@
                         true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */,
                         false /* showSubtitle*/);
                 mTitleIcon.setImageDrawable(getSpeakerDrawable());
-                mBottomDivider.setVisibility(View.VISIBLE);
                 mCheckBox.setVisibility(View.GONE);
                 mAddIcon.setVisibility(View.GONE);
                 initSessionSeekbar();
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
index 1300400..f1c6601 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
@@ -17,6 +17,7 @@
 package com.android.systemui.media.dialog;
 
 import android.content.Context;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.view.View;
 import android.view.WindowManager;
@@ -28,6 +29,7 @@
 /**
  * Dialog for media output group.
  */
+// TODO(b/203073091): Remove this class once group logic been implemented.
 public class MediaOutputGroupDialog extends MediaOutputBaseDialog {
 
     MediaOutputGroupDialog(Context context, boolean aboveStatusbar, MediaOutputController
@@ -76,6 +78,11 @@
     }
 
     @Override
+    Drawable getAppSourceIcon() {
+        return null;
+    }
+
+    @Override
     int getStopButtonVisibility() {
         return View.VISIBLE;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttChipController.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttChipController.kt
new file mode 100644
index 0000000..85e5b33
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttChipController.kt
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2021 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.taptotransfer
+
+import android.content.Context
+import android.graphics.PixelFormat
+import android.view.Gravity
+import android.view.WindowManager
+import android.widget.TextView
+import androidx.annotation.VisibleForTesting
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.commandline.Command
+import com.android.systemui.statusbar.commandline.CommandRegistry
+import java.io.PrintWriter
+import javax.inject.Inject
+
+/**
+ * A controller to display and hide the Media Tap-To-Transfer chip. This chip is shown when a user
+ * is currently playing media on a local "media cast sender" device (e.g. a phone) and gets close
+ * enough to a "media cast receiver" device (e.g. a tablet). This chip encourages the user to
+ * transfer the media from the sender device to the receiver device.
+ */
+@SysUISingleton
+class MediaTttChipController @Inject constructor(
+    context: Context,
+    commandRegistry: CommandRegistry,
+    private val windowManager: WindowManager,
+) {
+    init {
+        commandRegistry.registerCommand(ADD_CHIP_COMMAND_TAG) { AddChipCommand() }
+        commandRegistry.registerCommand(REMOVE_CHIP_COMMAND_TAG) { RemoveChipCommand() }
+    }
+
+    private val windowLayoutParams = WindowManager.LayoutParams().apply {
+        width = WindowManager.LayoutParams.MATCH_PARENT
+        height = WindowManager.LayoutParams.MATCH_PARENT
+        gravity = Gravity.CENTER_HORIZONTAL
+        type = WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY
+        title = "Media Tap-To-Transfer Chip View"
+        flags = (WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                or WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE)
+        format = PixelFormat.TRANSLUCENT
+        setTrustedOverlay()
+    }
+
+    // TODO(b/203800327): Create a layout that matches UX.
+    private val chipView: TextView = TextView(context).apply {
+        text = "Media Tap-To-Transfer Chip"
+    }
+
+    private var chipDisplaying: Boolean = false
+
+    private fun addChip() {
+        if (chipDisplaying) { return }
+        windowManager.addView(chipView, windowLayoutParams)
+        chipDisplaying = true
+    }
+
+    private fun removeChip() {
+        if (!chipDisplaying) { return }
+        windowManager.removeView(chipView)
+        chipDisplaying = false
+    }
+
+    inner class AddChipCommand : Command {
+        override fun execute(pw: PrintWriter, args: List<String>) = addChip()
+        override fun help(pw: PrintWriter) {
+            pw.println("Usage: adb shell cmd statusbar $ADD_CHIP_COMMAND_TAG")
+        }
+    }
+
+    inner class RemoveChipCommand : Command {
+        override fun execute(pw: PrintWriter, args: List<String>) = removeChip()
+        override fun help(pw: PrintWriter) {
+            pw.println("Usage: adb shell cmd statusbar $REMOVE_CHIP_COMMAND_TAG")
+        }
+    }
+
+    companion object {
+        @VisibleForTesting
+        const val ADD_CHIP_COMMAND_TAG = "media-ttt-chip-add"
+        @VisibleForTesting
+        const val REMOVE_CHIP_COMMAND_TAG = "media-ttt-chip-remove"
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt
new file mode 100644
index 0000000..03bc935
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2021 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.taptotransfer
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import javax.inject.Inject
+
+/** Flags related to media tap-to-transfer. */
+@SysUISingleton
+class MediaTttFlags @Inject constructor(private val featureFlags: FeatureFlags) {
+    /** */
+    fun isMediaTttEnabled(): Boolean = featureFlags.isEnabled(Flags.MEDIA_TAP_TO_TRANSFER)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
new file mode 100644
index 0000000..25337b6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavBarHelper.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2021 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.navigationbar;
+
+import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
+
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.inputmethodservice.InputMethodService;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.view.View;
+import android.view.WindowInsets;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.Dumpable;
+import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.shared.system.QuickStepContract;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import javax.inject.Inject;
+
+import dagger.Lazy;
+
+/**
+ * Extracts shared elements between navbar and taskbar delegate to de-dupe logic and help them
+ * experience the joys of friendship.
+ * The events are then passed through
+ *
+ * Currently consolidates
+ * * A11y
+ * * Assistant
+ */
+@SysUISingleton
+public final class NavBarHelper implements
+        AccessibilityButtonModeObserver.ModeChangedListener,
+        OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener,
+        Dumpable {
+    private final AccessibilityManager mAccessibilityManager;
+    private final Lazy<AssistManager> mAssistManagerLazy;
+    private final Lazy<Optional<StatusBar>> mStatusBarOptionalLazy;
+    private final UserTracker mUserTracker;
+    private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
+    private final List<NavbarTaskbarStateUpdater> mA11yEventListeners = new ArrayList<>();
+    private final Context mContext;
+    private ContentResolver mContentResolver;
+    private boolean mAssistantAvailable;
+    private boolean mLongPressHomeEnabled;
+    private boolean mAssistantTouchGestureEnabled;
+    private int mNavBarMode;
+
+    private final ContentObserver mAssistContentObserver = new ContentObserver(
+            new Handler(Looper.getMainLooper())) {
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            updateAssitantAvailability();
+        }
+    };
+
+    /**
+     * @param context This is not display specific, then again neither is any of the code in
+     *                this class. Once there's display specific code, we may want to create an
+     *                instance of this class per navbar vs having it be a singleton.
+     */
+    @Inject
+    public NavBarHelper(Context context, AccessibilityManager accessibilityManager,
+            AccessibilityManagerWrapper accessibilityManagerWrapper,
+            AccessibilityButtonModeObserver accessibilityButtonModeObserver,
+            OverviewProxyService overviewProxyService,
+            Lazy<AssistManager> assistManagerLazy,
+            Lazy<Optional<StatusBar>> statusBarOptionalLazy,
+            NavigationModeController navigationModeController,
+            UserTracker userTracker,
+            DumpManager dumpManager) {
+        mContext = context;
+        mAccessibilityManager = accessibilityManager;
+        mAssistManagerLazy = assistManagerLazy;
+        mStatusBarOptionalLazy = statusBarOptionalLazy;
+        mUserTracker = userTracker;
+        accessibilityManagerWrapper.addCallback(
+                accessibilityManager1 -> NavBarHelper.this.dispatchA11yEventUpdate());
+        mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
+
+        mAccessibilityButtonModeObserver.addListener(this);
+        mNavBarMode = navigationModeController.addListener(this);
+        overviewProxyService.addCallback(this);
+        dumpManager.registerDumpable(this);
+    }
+
+    public void init() {
+        mContentResolver = mContext.getContentResolver();
+        mContentResolver.registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
+                false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
+        mContentResolver.registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED),
+                false, mAssistContentObserver, UserHandle.USER_ALL);
+        mContentResolver.registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED),
+                false, mAssistContentObserver, UserHandle.USER_ALL);
+        updateAssitantAvailability();
+    }
+
+    public void destroy() {
+        mContentResolver.unregisterContentObserver(mAssistContentObserver);
+    }
+
+    /**
+     * @param listener Will immediately get callbacks based on current state
+     */
+    public void registerNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) {
+        mA11yEventListeners.add(listener);
+        listener.updateAccessibilityServicesState();
+        listener.updateAssistantAvailable(mAssistantAvailable);
+    }
+
+    public void removeNavTaskStateUpdater(NavbarTaskbarStateUpdater listener) {
+        mA11yEventListeners.remove(listener);
+    }
+
+    private void dispatchA11yEventUpdate() {
+        for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) {
+            listener.updateAccessibilityServicesState();
+        }
+    }
+
+    private void dispatchAssistantEventUpdate(boolean assistantAvailable) {
+        for (NavbarTaskbarStateUpdater listener : mA11yEventListeners) {
+            listener.updateAssistantAvailable(assistantAvailable);
+        }
+    }
+
+    @Override
+    public void onAccessibilityButtonModeChanged(int mode) {
+        dispatchA11yEventUpdate();
+    }
+
+    /**
+     * See {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_CLICKABLE} and
+     * {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE}
+     *
+     * @return the a11y button clickable and long_clickable states, or 0 if there is no
+     *         a11y button in the navbar
+     */
+    public int getA11yButtonState() {
+        // AccessibilityManagerService resolves services for the current user since the local
+        // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission
+        final List<String> a11yButtonTargets =
+                mAccessibilityManager.getAccessibilityShortcutTargets(
+                        AccessibilityManager.ACCESSIBILITY_BUTTON);
+        final int requestingServices = a11yButtonTargets.size();
+
+        // If accessibility button is floating menu mode, click and long click state should be
+        // disabled.
+        if (mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()
+                == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU) {
+            return 0;
+        }
+
+        return (requestingServices >= 1 ? SYSUI_STATE_A11Y_BUTTON_CLICKABLE : 0)
+                | (requestingServices >= 2 ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0);
+    }
+
+    @Override
+    public void onConnectionChanged(boolean isConnected) {
+        if (isConnected) {
+            updateAssitantAvailability();
+        }
+    }
+
+    private void updateAssitantAvailability() {
+        boolean assistantAvailableForUser = mAssistManagerLazy.get()
+                .getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
+        boolean longPressDefault = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault);
+        mLongPressHomeEnabled = Settings.Secure.getIntForUser(mContentResolver,
+                Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0,
+                mUserTracker.getUserId()) != 0;
+        boolean gestureDefault = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_assistTouchGestureEnabledDefault);
+        mAssistantTouchGestureEnabled = Settings.Secure.getIntForUser(mContentResolver,
+                Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0,
+                mUserTracker.getUserId()) != 0;
+
+        mAssistantAvailable = assistantAvailableForUser
+                && mAssistantTouchGestureEnabled
+                && QuickStepContract.isGesturalMode(mNavBarMode);
+        dispatchAssistantEventUpdate(mAssistantAvailable);
+    }
+
+    public boolean getLongPressHomeEnabled() {
+        return mLongPressHomeEnabled;
+    }
+
+    @Override
+    public void startAssistant(Bundle bundle) {
+        mAssistManagerLazy.get().startAssist(bundle);
+    }
+
+    @Override
+    public void onNavigationModeChanged(int mode) {
+        mNavBarMode = mode;
+        updateAssitantAvailability();
+    }
+
+    /**
+     * @return Whether the IME is shown on top of the screen given the {@code vis} flag of
+     * {@link InputMethodService} and the keyguard states.
+     */
+    public boolean isImeShown(int vis) {
+        View shadeWindowView = mStatusBarOptionalLazy.get().get().getNotificationShadeWindowView();
+        boolean isKeyguardShowing = mStatusBarOptionalLazy.get().get().isKeyguardShowing();
+        boolean imeVisibleOnShade = shadeWindowView != null && shadeWindowView.isAttachedToWindow()
+                && shadeWindowView.getRootWindowInsets().isVisible(WindowInsets.Type.ime());
+        return imeVisibleOnShade
+                || (!isKeyguardShowing && (vis & InputMethodService.IME_VISIBLE) != 0);
+    }
+
+    /**
+     * Callbacks will get fired once immediately after registering via
+     * {@link #registerNavTaskStateUpdater(NavbarTaskbarStateUpdater)}
+     */
+    public interface NavbarTaskbarStateUpdater {
+        void updateAccessibilityServicesState();
+        void updateAssistantAvailable(boolean available);
+    }
+
+    @Override
+    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+        pw.println("NavbarTaskbarFriendster");
+        pw.println("  longPressHomeEnabled=" + mLongPressHomeEnabled);
+        pw.println("  mAssistantTouchGestureEnabled=" + mAssistantTouchGestureEnabled);
+        pw.println("  mAssistantAvailable=" + mAssistantAvailable);
+        pw.println("  mNavBarMode=" + mNavBarMode);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index 0e6e8a4..8026df7 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -67,22 +67,17 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Configuration;
-import android.database.ContentObserver;
 import android.graphics.Insets;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.RectF;
-import android.inputmethodservice.InputMethodService;
-import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
-import android.provider.Settings;
 import android.telecom.TelecomManager;
 import android.text.TextUtils;
 import android.util.Log;
@@ -199,8 +194,7 @@
     private final Handler mHandler;
     private final NavigationBarOverlayController mNavbarOverlayController;
     private final UiEventLogger mUiEventLogger;
-    private final NavigationBarA11yHelper mNavigationBarA11yHelper;
-    private final UserTracker mUserTracker;
+    private final NavBarHelper mNavBarHelper;
     private final NotificationShadeDepthController mNotificationShadeDepthController;
 
     private Bundle mSavedState;
@@ -212,9 +206,7 @@
     private int mNavigationIconHints = 0;
     private @TransitionMode int mNavigationBarMode;
     private ContentResolver mContentResolver;
-    private boolean mAssistantAvailable;
     private boolean mLongPressHomeEnabled;
-    private boolean mAssistantTouchGestureEnabled;
 
     private int mDisabledFlags1;
     private int mDisabledFlags2;
@@ -308,16 +300,31 @@
         }
     };
 
+    private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater =
+            new NavBarHelper.NavbarTaskbarStateUpdater() {
+                @Override
+                public void updateAccessibilityServicesState() {
+                    updateAcessibilityStateFlags();
+                }
+
+                @Override
+                public void updateAssistantAvailable(boolean available) {
+                    // TODO(b/198002034): Content observers currently can still be called back after
+                    //  being unregistered, and in this case we can ignore the change if the nav bar
+                    //  has been destroyed already
+                    if (mNavigationBarView == null) {
+                        return;
+                    }
+                    mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled();
+                    updateAssistantEntrypoints(available);
+                }
+            };
+
     private final OverviewProxyListener mOverviewProxyListener = new OverviewProxyListener() {
         @Override
         public void onConnectionChanged(boolean isConnected) {
             mNavigationBarView.updateStates();
             updateScreenPinningGestures();
-
-            // Send the assistant availability upon connection
-            if (isConnected) {
-                updateAssistantEntrypoints();
-            }
         }
 
         @Override
@@ -420,20 +427,6 @@
         }
     };
 
-    private final ContentObserver mAssistContentObserver = new ContentObserver(
-            new Handler(Looper.getMainLooper())) {
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            // TODO(b/198002034): Content observers currently can still be called back after being
-            // unregistered, and in this case we can ignore the change if the nav bar has been
-            // destroyed already
-            if (mNavigationBarView == null) {
-                return;
-            }
-            updateAssistantEntrypoints();
-        }
-    };
-
     private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
             new DeviceConfig.OnPropertiesChangedListener() {
                 @Override
@@ -503,7 +496,7 @@
             @Main Handler mainHandler,
             NavigationBarOverlayController navbarOverlayController,
             UiEventLogger uiEventLogger,
-            NavigationBarA11yHelper navigationBarA11yHelper,
+            NavBarHelper navBarHelper,
             UserTracker userTracker,
             LightBarController mainLightBarController,
             LightBarController.Factory lightBarControllerFactory,
@@ -534,8 +527,7 @@
         mHandler = mainHandler;
         mNavbarOverlayController = navbarOverlayController;
         mUiEventLogger = uiEventLogger;
-        mNavigationBarA11yHelper = navigationBarA11yHelper;
-        mUserTracker = userTracker;
+        mNavBarHelper = navBarHelper;
         mNotificationShadeDepthController = notificationShadeDepthController;
         mMainLightBarController = mainLightBarController;
         mLightBarControllerFactory = lightBarControllerFactory;
@@ -567,18 +559,9 @@
         mIsOnDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
 
         mCommandQueue.addCallback(this);
-        mAssistantAvailable = mAssistManagerLazy.get()
-                .getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
+        mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled();
         mContentResolver = mContext.getContentResolver();
-        mContentResolver.registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.ASSISTANT),
-                false /* notifyForDescendants */, mAssistContentObserver, UserHandle.USER_ALL);
-        mContentResolver.registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED),
-                false, mAssistContentObserver, UserHandle.USER_ALL);
-        mContentResolver.registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED),
-                false, mAssistContentObserver, UserHandle.USER_ALL);
+        mNavBarHelper.init();
         mAllowForceNavBarHandleOpaque = mContext.getResources().getBoolean(
                 R.bool.allow_force_nav_bar_handle_opaque);
         mForceNavBarHandleOpaque = DeviceConfig.getBoolean(
@@ -592,7 +575,6 @@
         )).filter(duration -> duration != 0);
         DeviceConfig.addOnPropertiesChangedListener(
                 DeviceConfig.NAMESPACE_SYSTEMUI, mHandler::post, mOnPropertiesChangedListener);
-        updateAssistantEntrypoints();
 
         if (savedState != null) {
             mDisabledFlags1 = savedState.getInt(EXTRA_DISABLE_STATE, 0);
@@ -619,8 +601,8 @@
         mWindowManager.removeViewImmediate(mNavigationBarView.getRootView());
         mNavigationModeController.removeListener(this);
 
-        mNavigationBarA11yHelper.removeA11yEventListener(mAccessibilityListener);
-        mContentResolver.unregisterContentObserver(mAssistContentObserver);
+        mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+        mNavBarHelper.destroy();
         mDeviceProvisionedController.removeCallback(mUserSetupListener);
         mNotificationShadeDepthController.removeListener(mDepthListener);
 
@@ -642,7 +624,7 @@
         mNavigationBarView.setWindowVisible(isNavBarWindowVisible());
         mNavigationBarView.setBehavior(mBehavior);
 
-        mNavigationBarA11yHelper.registerA11yEventListener(mAccessibilityListener);
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
 
         mSplitScreenOptional.ifPresent(mNavigationBarView::registerDockedListener);
         mPipOptional.ifPresent(mNavigationBarView::registerPipExclusionBoundsChangeListener);
@@ -715,7 +697,7 @@
         mHandler.removeCallbacks(mAutoDim);
         mHandler.removeCallbacks(mOnVariableDurationHomeLongClick);
         mHandler.removeCallbacks(mEnableLayoutTransitions);
-        mNavigationBarA11yHelper.removeA11yEventListener(mAccessibilityListener);
+        mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
         mFrame = null;
         mNavigationBarView = null;
         mOrientationHandle = null;
@@ -884,7 +866,6 @@
         pw.println("  mCurrentRotation=" + mCurrentRotation);
         pw.println("  mHomeButtonLongPressDurationMs=" + mHomeButtonLongPressDurationMs);
         pw.println("  mLongPressHomeEnabled=" + mLongPressHomeEnabled);
-        pw.println("  mAssistantTouchGestureEnabled=" + mAssistantTouchGestureEnabled);
         pw.println("  mNavigationBarWindowState="
                 + windowStateToString(mNavigationBarWindowState));
         pw.println("  mNavigationBarMode="
@@ -901,7 +882,8 @@
         if (displayId != mDisplayId) {
             return;
         }
-        boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0;
+        boolean imeShown = mNavBarHelper.isImeShown(vis);
+        showImeSwitcher = imeShown && showImeSwitcher;
         int hints = Utilities.calculateBackDispositionHints(mNavigationIconHints, backDisposition,
                 imeShown, showImeSwitcher);
         if (hints == mNavigationIconHints) return;
@@ -1164,7 +1146,7 @@
         ButtonDispatcher accessibilityButton = mNavigationBarView.getAccessibilityButton();
         accessibilityButton.setOnClickListener(this::onAccessibilityClick);
         accessibilityButton.setOnLongClickListener(this::onAccessibilityLongClick);
-        updateAccessibilityServicesState();
+        updateAcessibilityStateFlags();
 
         ButtonDispatcher imeSwitcherButton = mNavigationBarView.getImeSwitchButton();
         imeSwitcherButton.setOnClickListener(this::onImeSwitcherClick);
@@ -1389,8 +1371,8 @@
         return true;
     }
 
-    void updateAccessibilityServicesState() {
-        int a11yFlags = mNavigationBarA11yHelper.getA11yButtonState();
+    void updateAcessibilityStateFlags() {
+        int a11yFlags = mNavBarHelper.getA11yButtonState();
 
         if (mNavigationBarView != null) {
             boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
@@ -1402,7 +1384,7 @@
 
     public void updateSystemUiStateFlags(int a11yFlags) {
         if (a11yFlags < 0) {
-            a11yFlags = mNavigationBarA11yHelper.getA11yButtonState();
+            a11yFlags = mNavBarHelper.getA11yButtonState();
         }
         boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
         boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0;
@@ -1429,24 +1411,10 @@
         }
     }
 
-    private void updateAssistantEntrypoints() {
-        mAssistantAvailable = mAssistManagerLazy.get()
-                .getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
-        boolean longPressDefault = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault);
-        mLongPressHomeEnabled = Settings.Secure.getIntForUser(mContentResolver,
-                Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0,
-                mUserTracker.getUserId()) != 0;
-        boolean gestureDefault = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_assistTouchGestureEnabledDefault);
-        mAssistantTouchGestureEnabled = Settings.Secure.getIntForUser(mContentResolver,
-                Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0,
-                mUserTracker.getUserId()) != 0;
+    private void updateAssistantEntrypoints(boolean assistantAvailable) {
         if (mOverviewProxyService.getProxy() != null) {
             try {
-                mOverviewProxyService.getProxy().onAssistantAvailable(mAssistantAvailable
-                        && mAssistantTouchGestureEnabled
-                        && QuickStepContract.isGesturalMode(mNavBarMode));
+                mOverviewProxyService.getProxy().onAssistantAvailable(assistantAvailable);
             } catch (RemoteException e) {
                 Log.w(TAG, "Unable to send assistant availability data to launcher");
             }
@@ -1517,8 +1485,6 @@
     @Override
     public void onNavigationModeChanged(int mode) {
         mNavBarMode = mode;
-        // update assistant entry points on system navigation radio button click
-        updateAssistantEntrypoints();
 
         if (!QuickStepContract.isGesturalMode(mode)) {
             // Reset the override alpha
@@ -1557,9 +1523,6 @@
         mNavigationBarView.getBarTransitions().finishAnimations();
     }
 
-    private final NavigationBarA11yHelper.NavA11yEventListener mAccessibilityListener =
-            this::updateAccessibilityServicesState;
-
     private WindowManager.LayoutParams getBarLayoutParams(int rotation) {
         WindowManager.LayoutParams lp = getBarLayoutParamsForRotation(rotation);
         lp.paramsForRotation = new WindowManager.LayoutParams[4];
@@ -1663,7 +1626,7 @@
             }
             if (Intent.ACTION_USER_SWITCHED.equals(action)) {
                 // The accessibility settings may be different for the new user
-                updateAccessibilityServicesState();
+                updateAcessibilityStateFlags();
             }
         }
     };
@@ -1699,7 +1662,7 @@
         private final Handler mMainHandler;
         private final NavigationBarOverlayController mNavbarOverlayController;
         private final UiEventLogger mUiEventLogger;
-        private final NavigationBarA11yHelper mNavigationBarA11yHelper;
+        private final NavBarHelper mNavBarHelper;
         private final UserTracker mUserTracker;
         private final LightBarController mMainLightBarController;
         private final LightBarController.Factory mLightBarControllerFactory;
@@ -1732,7 +1695,7 @@
                 @Main Handler mainHandler,
                 NavigationBarOverlayController navbarOverlayController,
                 UiEventLogger uiEventLogger,
-                NavigationBarA11yHelper navigationBarA11yHelper,
+                NavBarHelper navBarHelper,
                 UserTracker userTracker,
                 LightBarController mainLightBarController,
                 LightBarController.Factory lightBarControllerFactory,
@@ -1762,7 +1725,7 @@
             mMainHandler = mainHandler;
             mNavbarOverlayController = navbarOverlayController;
             mUiEventLogger = uiEventLogger;
-            mNavigationBarA11yHelper = navigationBarA11yHelper;
+            mNavBarHelper = navBarHelper;
             mUserTracker = userTracker;
             mMainLightBarController = mainLightBarController;
             mLightBarControllerFactory = lightBarControllerFactory;
@@ -1783,7 +1746,7 @@
                     mSplitScreenOptional, mRecentsOptional, mStatusBarOptionalLazy,
                     mShadeController, mNotificationRemoteInputManager,
                     mNotificationShadeDepthController, mSystemActions, mMainHandler,
-                    mNavbarOverlayController, mUiEventLogger, mNavigationBarA11yHelper,
+                    mNavbarOverlayController, mUiEventLogger, mNavBarHelper,
                     mUserTracker, mMainLightBarController, mLightBarControllerFactory,
                     mMainAutoHideController, mAutoHideControllerFactory, mTelecomManagerOptional,
                     mInputMethodManager);
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java
deleted file mode 100644
index 13e6d8b..0000000
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarA11yHelper.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package com.android.systemui.navigationbar;
-
-import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU;
-
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
-import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
-
-import android.view.accessibility.AccessibilityManager;
-
-import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.shared.system.QuickStepContract;
-import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-/**
- * Extracts shared elements of a11y necessary between navbar and taskbar delegate
- */
-@SysUISingleton
-public final class NavigationBarA11yHelper implements
-        AccessibilityButtonModeObserver.ModeChangedListener {
-    private final AccessibilityManager mAccessibilityManager;
-    private final AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
-    private final List<NavA11yEventListener> mA11yEventListeners = new ArrayList<>();
-
-    @Inject
-    public NavigationBarA11yHelper(AccessibilityManager accessibilityManager,
-            AccessibilityManagerWrapper accessibilityManagerWrapper,
-            AccessibilityButtonModeObserver accessibilityButtonModeObserver) {
-        mAccessibilityManager = accessibilityManager;
-        accessibilityManagerWrapper.addCallback(
-                accessibilityManager1 -> NavigationBarA11yHelper.this.dispatchEventUpdate());
-        mAccessibilityButtonModeObserver = accessibilityButtonModeObserver;
-
-        mAccessibilityButtonModeObserver.addListener(this);
-    }
-
-    public void registerA11yEventListener(NavA11yEventListener listener) {
-        mA11yEventListeners.add(listener);
-    }
-
-    public void removeA11yEventListener(NavA11yEventListener listener) {
-        mA11yEventListeners.remove(listener);
-    }
-
-    private void dispatchEventUpdate() {
-        for (NavA11yEventListener listener : mA11yEventListeners) {
-            listener.updateAccessibilityServicesState();
-        }
-    }
-
-    @Override
-    public void onAccessibilityButtonModeChanged(int mode) {
-        dispatchEventUpdate();
-    }
-
-    /**
-     * See {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_CLICKABLE} and
-     * {@link QuickStepContract#SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE}
-     *
-     * @return the a11y button clickable and long_clickable states, or 0 if there is no
-     *         a11y button in the navbar
-     */
-    public int getA11yButtonState() {
-        // AccessibilityManagerService resolves services for the current user since the local
-        // AccessibilityManager is created from a Context with the INTERACT_ACROSS_USERS permission
-        final List<String> a11yButtonTargets =
-                mAccessibilityManager.getAccessibilityShortcutTargets(
-                        AccessibilityManager.ACCESSIBILITY_BUTTON);
-        final int requestingServices = a11yButtonTargets.size();
-
-        // If accessibility button is floating menu mode, click and long click state should be
-        // disabled.
-        if (mAccessibilityButtonModeObserver.getCurrentAccessibilityButtonMode()
-                == ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU) {
-            return 0;
-        }
-
-        return (requestingServices >= 1 ? SYSUI_STATE_A11Y_BUTTON_CLICKABLE : 0)
-                | (requestingServices >= 2 ? SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE : 0);
-    }
-
-    public interface NavA11yEventListener {
-        void updateAccessibilityServicesState();
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
index 3dc79c4..0429c02 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController.java
@@ -57,6 +57,7 @@
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
+import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import java.io.FileDescriptor;
@@ -100,11 +101,12 @@
             CommandQueue commandQueue,
             @Main Handler mainHandler,
             ConfigurationController configurationController,
-            NavigationBarA11yHelper navigationBarA11yHelper,
+            NavBarHelper navBarHelper,
             TaskbarDelegate taskbarDelegate,
             NavigationBar.Factory navigationBarFactory,
             DumpManager dumpManager,
-            AutoHideController autoHideController) {
+            AutoHideController autoHideController,
+            LightBarController lightBarController) {
         mContext = context;
         mHandler = mainHandler;
         mNavigationBarFactory = navigationBarFactory;
@@ -115,8 +117,8 @@
         mNavMode = navigationModeController.addListener(this);
         mTaskbarDelegate = taskbarDelegate;
         mTaskbarDelegate.setDependencies(commandQueue, overviewProxyService,
-                navigationBarA11yHelper, navigationModeController, sysUiFlagsContainer,
-                dumpManager, autoHideController);
+                navBarHelper, navigationModeController, sysUiFlagsContainer,
+                dumpManager, autoHideController, lightBarController);
         mIsTablet = isTablet(mContext);
         dumpManager.registerDumpable(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
index 680cc5c..7c8c3e0 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java
@@ -110,6 +110,7 @@
     private final int mNavColorSampleMargin;
     private final SysUiState mSysUiFlagContainer;
 
+    // The current view is one of mHorizontal or mVertical depending on the current configuration
     View mCurrentView = null;
     private View mVertical;
     private View mHorizontal;
@@ -397,12 +398,6 @@
         }
     }
 
-    @Override
-    protected boolean onSetAlpha(int alpha) {
-        Log.e(TAG, "onSetAlpha", new Throwable());
-        return super.onSetAlpha(alpha);
-    }
-
     public void setAutoHideController(AutoHideController autoHideController) {
         mAutoHideController = autoHideController;
     }
@@ -505,6 +500,18 @@
         return mCurrentView;
     }
 
+    /**
+     * Applies {@param consumer} to each of the nav bar views.
+     */
+    public void forEachView(Consumer<View> consumer) {
+        if (mVertical != null) {
+            consumer.accept(mVertical);
+        }
+        if (mHorizontal != null) {
+            consumer.accept(mHorizontal);
+        }
+    }
+
     public RotationButtonController getRotationButtonController() {
         return mRotationButtonController;
     }
@@ -1205,7 +1212,9 @@
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         mTmpLastConfiguration.updateFrom(mConfiguration);
-        mConfiguration.updateFrom(newConfig);
+        final int changes = mConfiguration.updateFrom(newConfig);
+        mFloatingRotationButton.onConfigurationChanged(changes);
+
         boolean uiCarModeChanged = updateCarMode();
         updateIcons(mTmpLastConfiguration);
         updateRecentsIcon();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index d707dbd..8fb394c 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -41,8 +41,9 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.hardware.display.DisplayManager;
-import android.inputmethodservice.InputMethodService;
 import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
 import android.view.Display;
 import android.view.InsetsVisibilities;
 import android.view.View;
@@ -62,6 +63,9 @@
 import com.android.systemui.statusbar.AutoHideUiElement;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.BarTransitions;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LightBarTransitionsController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -73,19 +77,32 @@
 public class TaskbarDelegate implements CommandQueue.Callbacks,
         OverviewProxyService.OverviewProxyListener, NavigationModeController.ModeChangedListener,
         ComponentCallbacks, Dumpable {
+    private static final String TAG = TaskbarDelegate.class.getSimpleName();
 
     private final EdgeBackGestureHandler mEdgeBackGestureHandler;
-
+    private boolean mInitialized;
     private CommandQueue mCommandQueue;
     private OverviewProxyService mOverviewProxyService;
-    private NavigationBarA11yHelper mNavigationBarA11yHelper;
+    private NavBarHelper mNavBarHelper;
     private NavigationModeController mNavigationModeController;
     private SysUiState mSysUiState;
     private AutoHideController mAutoHideController;
+    private LightBarController mLightBarController;
+    private LightBarTransitionsController mLightBarTransitionsController;
     private int mDisplayId;
     private int mNavigationIconHints;
-    private final NavigationBarA11yHelper.NavA11yEventListener mNavA11yEventListener =
-            this::updateSysuiFlags;
+    private final NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater =
+            new NavBarHelper.NavbarTaskbarStateUpdater() {
+                @Override
+                public void updateAccessibilityServicesState() {
+                    updateSysuiFlags();
+                }
+
+                @Override
+                public void updateAssistantAvailable(boolean available) {
+                    updateAssistantAvailability(available);
+                }
+            };
     private int mDisabledFlags;
     private @WindowVisibleState int mTaskBarWindowState = WINDOW_STATE_SHOWING;
     private @Behavior int mBehavior;
@@ -125,27 +142,56 @@
 
     public void setDependencies(CommandQueue commandQueue,
             OverviewProxyService overviewProxyService,
-            NavigationBarA11yHelper navigationBarA11yHelper,
+            NavBarHelper navBarHelper,
             NavigationModeController navigationModeController,
             SysUiState sysUiState, DumpManager dumpManager,
-            AutoHideController autoHideController) {
+            AutoHideController autoHideController,
+            LightBarController lightBarController) {
         // TODO: adding this in the ctor results in a dagger dependency cycle :(
         mCommandQueue = commandQueue;
         mOverviewProxyService = overviewProxyService;
-        mNavigationBarA11yHelper = navigationBarA11yHelper;
+        mNavBarHelper = navBarHelper;
         mNavigationModeController = navigationModeController;
         mSysUiState = sysUiState;
         dumpManager.registerDumpable(this);
         mAutoHideController = autoHideController;
+        mLightBarController = lightBarController;
+        mLightBarTransitionsController = createLightBarTransitionsController();
+    }
+
+    // Separated into a method to keep setDependencies() clean/readable.
+    private LightBarTransitionsController createLightBarTransitionsController() {
+        return new LightBarTransitionsController(mContext,
+                new LightBarTransitionsController.DarkIntensityApplier() {
+                    @Override
+                    public void applyDarkIntensity(float darkIntensity) {
+                        mOverviewProxyService.onNavButtonsDarkIntensityChanged(darkIntensity);
+                    }
+
+                    @Override
+                    public int getTintAnimationDuration() {
+                        return LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION;
+                    }
+                }, mCommandQueue) {
+            @Override
+            public boolean supportsIconTintForNavMode(int navigationMode) {
+                // Always tint taskbar nav buttons (region sampling handles gesture bar separately).
+                return true;
+            }
+        };
     }
 
     public void init(int displayId) {
+        if (mInitialized) {
+            return;
+        }
         mDisplayId = displayId;
         mCommandQueue.addCallback(this);
         mOverviewProxyService.addCallback(this);
         mEdgeBackGestureHandler.onNavigationModeChanged(
                 mNavigationModeController.addListener(this));
-        mNavigationBarA11yHelper.registerA11yEventListener(mNavA11yEventListener);
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+        mNavBarHelper.init();
         mEdgeBackGestureHandler.onNavBarAttached();
         // Initialize component callback
         Display display = mDisplayManager.getDisplay(displayId);
@@ -154,23 +200,32 @@
         // Set initial state for any listeners
         updateSysuiFlags();
         mAutoHideController.setNavigationBar(mAutoHideUiElement);
+        mLightBarController.setNavigationBar(mLightBarTransitionsController);
+        mInitialized = true;
     }
 
     public void destroy() {
+        if (!mInitialized) {
+            return;
+        }
         mCommandQueue.removeCallback(this);
         mOverviewProxyService.removeCallback(this);
         mNavigationModeController.removeListener(this);
-        mNavigationBarA11yHelper.removeA11yEventListener(mNavA11yEventListener);
+        mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+        mNavBarHelper.destroy();
         mEdgeBackGestureHandler.onNavBarDetached();
         if (mWindowContext != null) {
             mWindowContext.unregisterComponentCallbacks(this);
             mWindowContext = null;
         }
         mAutoHideController.setNavigationBar(null);
+        mLightBarTransitionsController.destroy(mContext);
+        mLightBarController.setNavigationBar(null);
+        mInitialized = false;
     }
 
     private void updateSysuiFlags() {
-        int a11yFlags = mNavigationBarA11yHelper.getA11yButtonState();
+        int a11yFlags = mNavBarHelper.getA11yButtonState();
         boolean clickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0;
         boolean longClickable = (a11yFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0;
 
@@ -194,10 +249,23 @@
                 .commitUpdate(mDisplayId);
     }
 
+    private void updateAssistantAvailability(boolean assistantAvailable) {
+        if (mOverviewProxyService.getProxy() == null) {
+            return;
+        }
+
+        try {
+            mOverviewProxyService.getProxy().onAssistantAvailable(assistantAvailable);
+        } catch (RemoteException e) {
+            Log.e(TAG, "onAssistantAvailable() failed, available: " + assistantAvailable, e);
+        }
+    }
+
     @Override
     public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
             boolean showImeSwitcher) {
-        boolean imeShown = (vis & InputMethodService.IME_VISIBLE) != 0;
+        boolean imeShown = mNavBarHelper.isImeShown(vis);
+        showImeSwitcher = imeShown && showImeSwitcher;
         int hints = Utilities.calculateBackDispositionHints(mNavigationIconHints, backDisposition,
                 imeShown, showImeSwitcher);
         if (hints != mNavigationIconHints) {
@@ -233,6 +301,10 @@
             AppearanceRegion[] appearanceRegions, boolean navbarColorManagedByIme, int behavior,
             InsetsVisibilities requestedVisibilities, String packageName) {
         mOverviewProxyService.onSystemBarAttributesChanged(displayId, behavior);
+        if (mLightBarController != null && displayId == mDisplayId) {
+            mLightBarController.onNavigationBarAppearanceChanged(appearance, false/*nbModeChanged*/,
+                    BarTransitions.MODE_TRANSPARENT /*navigationBarMode*/, navbarColorManagedByIme);
+        }
         if (mBehavior != behavior) {
             mBehavior = behavior;
             updateSysuiFlags();
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index fa37c86..5afefa1 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -100,8 +100,7 @@
     private static final int MAX_NUM_LOGGED_PREDICTIONS = 10;
     private static final int MAX_NUM_LOGGED_GESTURES = 10;
 
-    // Temporary log until b/201642126 is resolved
-    static final boolean DEBUG_MISSING_GESTURE = true;
+    static final boolean DEBUG_MISSING_GESTURE = false;
     static final String DEBUG_MISSING_GESTURE_TAG = "NoBackGesture";
 
     private ISystemGestureExclusionListener mGestureExclusionListener =
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
index 98b9146..e10e4d8 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt
@@ -17,8 +17,10 @@
 package com.android.systemui.qs
 
 import android.content.Intent
+import android.os.Handler
 import android.os.UserManager
 import android.provider.Settings
+import android.provider.Settings.Global.USER_SWITCHER_ENABLED
 import android.view.View
 import android.widget.Toast
 import androidx.annotation.VisibleForTesting
@@ -35,6 +37,7 @@
 import com.android.systemui.qs.FooterActionsController.ExpansionState.COLLAPSED
 import com.android.systemui.qs.FooterActionsController.ExpansionState.EXPANDED
 import com.android.systemui.qs.dagger.QSFlagsModule.PM_LITE_ENABLED
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.phone.MultiUserSwitchController
 import com.android.systemui.statusbar.phone.SettingsButton
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
@@ -42,6 +45,7 @@
 import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener
 import com.android.systemui.tuner.TunerService
 import com.android.systemui.util.ViewController
+import com.android.systemui.util.settings.GlobalSettings
 import javax.inject.Inject
 import javax.inject.Named
 
@@ -55,6 +59,7 @@
     private val qsPanelController: QSPanelController,
     private val activityStarter: ActivityStarter,
     private val userManager: UserManager,
+    private val userTracker: UserTracker,
     private val userInfoController: UserInfoController,
     private val multiUserSwitchController: MultiUserSwitchController,
     private val deviceProvisionedController: DeviceProvisionedController,
@@ -64,7 +69,9 @@
     private val globalActionsDialog: GlobalActionsDialogLite,
     private val uiEventLogger: UiEventLogger,
     @Named(PM_LITE_ENABLED) private val showPMLiteButton: Boolean,
-    private val buttonsVisibleState: ExpansionState
+    private val buttonsVisibleState: ExpansionState,
+    private val globalSetting: GlobalSettings,
+    private val handler: Handler
 ) : ViewController<FooterActionsView>(view) {
 
     enum class ExpansionState { COLLAPSED, EXPANDED }
@@ -83,6 +90,16 @@
         mView.onUserInfoChanged(picture, isGuestUser)
     }
 
+    private val multiUserSetting =
+            object : SettingObserver(
+                    globalSetting, handler, USER_SWITCHER_ENABLED, userTracker.userId) {
+                override fun handleValueChanged(value: Int, observedChange: Boolean) {
+                    if (observedChange) {
+                        updateView()
+                    }
+                }
+            }
+
     private val onClickListener = View.OnClickListener { v ->
         // Don't do anything until views are unhidden. Don't do anything if the tap looks
         // suspicious.
@@ -116,7 +133,7 @@
             }
         } else if (v === powerMenuLite) {
             uiEventLogger.log(GlobalActionsDialogLite.GlobalActionsEvent.GA_OPEN_QS)
-            globalActionsDialog.showOrHideDialog(false, true)
+            globalActionsDialog.showOrHideDialog(false, true, v)
         }
     }
 
@@ -182,6 +199,7 @@
             return
         }
         this.listening = listening
+        multiUserSetting.isListening = listening
         if (this.listening) {
             userInfoController.addCallback(onUserInfoChangedListener)
             updateView()
@@ -215,4 +233,4 @@
     }
 
     private fun isTunerEnabled() = tunerService.isTunerEnabled
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt
index f6c89a9..dd4dc87 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsControllerBuilder.kt
@@ -16,18 +16,22 @@
 
 package com.android.systemui.qs
 
+import android.os.Handler
 import android.os.UserManager
 import com.android.internal.logging.MetricsLogger
 import com.android.internal.logging.UiEventLogger
+import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.globalactions.GlobalActionsDialogLite
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.qs.FooterActionsController.ExpansionState
 import com.android.systemui.qs.dagger.QSFlagsModule
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.phone.MultiUserSwitchController
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.statusbar.policy.UserInfoController
 import com.android.systemui.tuner.TunerService
+import com.android.systemui.util.settings.GlobalSettings
 import javax.inject.Inject
 import javax.inject.Named
 
@@ -35,6 +39,7 @@
     private val qsPanelController: QSPanelController,
     private val activityStarter: ActivityStarter,
     private val userManager: UserManager,
+    private val userTracker: UserTracker,
     private val userInfoController: UserInfoController,
     private val multiUserSwitchControllerFactory: MultiUserSwitchController.Factory,
     private val deviceProvisionedController: DeviceProvisionedController,
@@ -43,7 +48,9 @@
     private val tunerService: TunerService,
     private val globalActionsDialog: GlobalActionsDialogLite,
     private val uiEventLogger: UiEventLogger,
-    @Named(QSFlagsModule.PM_LITE_ENABLED) private val showPMLiteButton: Boolean
+    @Named(QSFlagsModule.PM_LITE_ENABLED) private val showPMLiteButton: Boolean,
+    private val globalSettings: GlobalSettings,
+    @Main private val handler: Handler
 ) {
     private lateinit var view: FooterActionsView
     private lateinit var buttonsVisibleState: ExpansionState
@@ -60,8 +67,9 @@
 
     fun build(): FooterActionsController {
         return FooterActionsController(view, qsPanelController, activityStarter, userManager,
-                userInfoController, multiUserSwitchControllerFactory.create(view),
+                userTracker, userInfoController, multiUserSwitchControllerFactory.create(view),
                 deviceProvisionedController, falsingManager, metricsLogger, tunerService,
-                globalActionsDialog, uiEventLogger, showPMLiteButton, buttonsVisibleState)
+                globalActionsDialog, uiEventLogger, showPMLiteButton, buttonsVisibleState,
+                globalSettings, handler)
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java b/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java
deleted file mode 100644
index c169df0..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/GlobalSetting.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2014 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.qs;
-
-import android.content.Context;
-import android.database.ContentObserver;
-import android.os.Handler;
-import android.provider.Settings.Global;
-
-import com.android.systemui.statusbar.policy.Listenable;
-
-/** Helper for managing a global setting. **/
-public abstract class GlobalSetting extends ContentObserver implements Listenable {
-    private final Context mContext;
-    private final String mSettingName;
-
-    protected abstract void handleValueChanged(int value);
-
-    public GlobalSetting(Context context, Handler handler, String settingName) {
-        super(handler);
-        mContext = context;
-        mSettingName = settingName;
-    }
-
-    public int getValue() {
-        return Global.getInt(mContext.getContentResolver(), mSettingName, 0);
-    }
-
-    public void setValue(int value) {
-        Global.putInt(mContext.getContentResolver(), mSettingName, value);
-    }
-
-    @Override
-    public void setListening(boolean listening) {
-        if (listening) {
-            mContext.getContentResolver().registerContentObserver(
-                    Global.getUriFor(mSettingName), false, this);
-        } else {
-            mContext.getContentResolver().unregisterContentObserver(this);
-        }
-    }
-
-    @Override
-    public void onChange(boolean selfChange) {
-        handleValueChanged(getValue());
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index cdf770f..b533ac4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -1,5 +1,7 @@
 package com.android.systemui.qs;
 
+import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
@@ -20,6 +22,7 @@
 import androidx.viewpager.widget.PagerAdapter;
 import androidx.viewpager.widget.ViewPager;
 
+import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.QSTile;
@@ -533,6 +536,11 @@
 
     private final ViewPager.OnPageChangeListener mOnPageChangeListener =
             new ViewPager.SimpleOnPageChangeListener() {
+
+                private int mCurrentScrollState = SCROLL_STATE_IDLE;
+                // Flag to avoid redundant call InteractionJankMonitor::begin()
+                private boolean mIsScrollJankTraceBegin = false;
+
                 @Override
                 public void onPageSelected(int position) {
                     updateSelected();
@@ -546,6 +554,13 @@
                 @Override
                 public void onPageScrolled(int position, float positionOffset,
                         int positionOffsetPixels) {
+
+                    if (!mIsScrollJankTraceBegin && mCurrentScrollState == SCROLL_STATE_DRAGGING) {
+                        InteractionJankMonitor.getInstance().begin(PagedTileLayout.this,
+                                CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE);
+                        mIsScrollJankTraceBegin = true;
+                    }
+
                     if (mPageIndicator == null) return;
                     mPageIndicatorPosition = position + positionOffset;
                     mPageIndicator.setLocation(mPageIndicatorPosition);
@@ -554,6 +569,16 @@
                                 (isLayoutRtl() ? position == mPages.size() - 1 : position == 0));
                     }
                 }
+
+                @Override
+                public void onPageScrollStateChanged(int state) {
+                    if (state != mCurrentScrollState && state == SCROLL_STATE_IDLE) {
+                        InteractionJankMonitor.getInstance().end(
+                                CUJ_NOTIFICATION_SHADE_QS_SCROLL_SWIPE);
+                        mIsScrollJankTraceBegin = false;
+                    }
+                    mCurrentScrollState = state;
+                }
             };
 
     private final PagerAdapter mAdapter = new PagerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java
index 2f189be..768598a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PseudoGridView.java
@@ -133,10 +133,7 @@
                     x += width + mHorizontalSpacing;
                 }
             }
-            y += maxHeight;
-            if (row > 0) {
-                y += mVerticalSpacing;
-            }
+            y += maxHeight + mVerticalSpacing;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index dd876b7..ee59ae6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -15,10 +15,10 @@
 package com.android.systemui.qs;
 
 import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
-import static com.android.systemui.statusbar.DisableFlagsLogger.DisableState;
 
 import static com.android.systemui.media.dagger.MediaModule.QS_PANEL;
 import static com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL;
+import static com.android.systemui.statusbar.DisableFlagsLogger.DisableState;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -696,6 +696,11 @@
         mQSPanelController.closeDetail();
     }
 
+    @Override
+    public void closeCustomizer() {
+        mQSCustomizerController.hide();
+    }
+
     public void notifyCustomizeChanged() {
         // The customize state changed, so our height changed.
         mContainer.updateExpansion();
@@ -765,6 +770,8 @@
         public void onAnimationEnd(Animator animation) {
             mHeaderAnimating = false;
             updateQsState();
+            // Unset the listener, otherwise this may persist for another view property animation
+            getView().animate().setListener(null);
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
index 17a815e..8544f61 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragmentDisableFlagsLogger.kt
@@ -4,7 +4,6 @@
 import com.android.systemui.log.LogLevel
 import com.android.systemui.log.dagger.QSFragmentDisableLog
 import com.android.systemui.statusbar.DisableFlagsLogger
-import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment
 import javax.inject.Inject
 
 /** A helper class for logging disable flag changes made in [QSFragment]. */
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 71eb4a2..d69deef 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -26,6 +26,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Message;
+import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Gravity;
@@ -103,6 +104,8 @@
     protected LinearLayout mHorizontalContentContainer;
 
     protected QSTileLayout mTileLayout;
+    private float mSquishinessFraction = 1f;
+    private final ArrayMap<View, Integer> mChildrenLayoutTop = new ArrayMap<>();
 
     public QSPanel(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -179,10 +182,26 @@
         if (mTileLayout == null) {
             mTileLayout = (QSTileLayout) LayoutInflater.from(mContext)
                     .inflate(R.layout.qs_paged_tile_layout, this, false);
+            mTileLayout.setSquishinessFraction(mSquishinessFraction);
         }
         return mTileLayout;
     }
 
+    public void setSquishinessFraction(float squishinessFraction) {
+        if (Float.compare(squishinessFraction, mSquishinessFraction) == 0) {
+            return;
+        }
+        mSquishinessFraction = squishinessFraction;
+        if (mTileLayout == null) {
+            return;
+        }
+        mTileLayout.setSquishinessFraction(squishinessFraction);
+        if (getMeasuredWidth() == 0) {
+            return;
+        }
+        updateViewPositions();
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         if (mTileLayout instanceof PagedTileLayout) {
@@ -228,6 +247,39 @@
         setMeasuredDimension(getMeasuredWidth(), height);
     }
 
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            mChildrenLayoutTop.put(child, child.getTop());
+        }
+        updateViewPositions();
+    }
+
+    private void updateViewPositions() {
+        if (!(mTileLayout instanceof TileLayout)) {
+            return;
+        }
+        TileLayout layout = (TileLayout) mTileLayout;
+
+        // Adjust view positions based on tile squishing
+        int tileHeightOffset = layout.getTilesHeight() - layout.getHeight();
+
+        boolean move = false;
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            if (move) {
+                int top = mChildrenLayoutTop.get(child);
+                child.setLeftTopRightBottom(child.getLeft(), top + tileHeightOffset,
+                        child.getRight(), top + tileHeightOffset + child.getHeight());
+            }
+            if (child == mTileLayout) {
+                move = true;
+            }
+        }
+    }
+
     protected String getDumpableTag() {
         return TAG;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index f7d1b1e..eddc206 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -147,6 +147,10 @@
         return mMediaHost;
     }
 
+    public void setSquishinessFraction(float squishinessFraction) {
+        mView.setSquishinessFraction(squishinessFraction);
+    }
+
     @Override
     protected void onViewAttached() {
         mQsTileRevealController = createTileRevealController();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt
index c1c146d..c680cb5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt
@@ -1,14 +1,10 @@
 package com.android.systemui.qs
 
-import android.view.ViewGroup
-import com.android.systemui.qs.dagger.QSFragmentModule.QQS_FOOTER
 import com.android.systemui.qs.dagger.QSScope
 import javax.inject.Inject
-import javax.inject.Named
 
 @QSScope
 class QSSquishinessController @Inject constructor(
-    @Named(QQS_FOOTER) private val qqsFooterActionsView: FooterActionsView,
     private val qsAnimator: QSAnimator,
     private val qsPanelController: QSPanelController,
     private val quickQSPanelController: QuickQSPanelController
@@ -33,23 +29,7 @@
      * Change the height of all tiles and repositions their siblings.
      */
     private fun updateSquishiness() {
-        (qsPanelController.tileLayout as QSPanel.QSTileLayout).setSquishinessFraction(squishiness)
-        val tileLayout = quickQSPanelController.tileLayout as TileLayout
-        tileLayout.setSquishinessFraction(squishiness)
-
-        // Calculate how much we should move the footer
-        val tileHeightOffset = tileLayout.height - tileLayout.tilesHeight
-        val footerTopMargin = (qqsFooterActionsView.layoutParams as ViewGroup.MarginLayoutParams)
-                .topMargin
-        val nextTop = tileLayout.bottom - tileHeightOffset + footerTopMargin
-        val amountMoved = nextTop - qqsFooterActionsView.top
-
-        // Move the footer and other siblings (MediaPlayer)
-        (qqsFooterActionsView.parent as ViewGroup?)?.let { parent ->
-            val index = parent.indexOfChild(qqsFooterActionsView)
-            for (i in index until parent.childCount) {
-                parent.getChildAt(i).top += amountMoved
-            }
-        }
+        qsPanelController.setSquishinessFraction(squishiness)
+        quickQSPanelController.setSquishinessFraction(squishiness)
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
index 0196769..c648e9b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileHost.java
@@ -53,6 +53,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.connectivity.StatusBarFlags;
 import com.android.systemui.statusbar.phone.AutoTileManager;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -110,6 +111,7 @@
     private SecureSettings mSecureSettings;
 
     private final TileServiceRequestController mTileServiceRequestController;
+    private final StatusBarFlags mStatusBarFlags;
 
     @Inject
     public QSTileHost(Context context,
@@ -129,7 +131,8 @@
             SecureSettings secureSettings,
             CustomTileStatePersister customTileStatePersister,
             TileServiceRequestController.Builder tileServiceRequestControllerBuilder,
-            FeatureFlags featureFlags
+            FeatureFlags featureFlags,
+            StatusBarFlags statusBarFlags
     ) {
         mIconController = iconController;
         mContext = context;
@@ -141,6 +144,7 @@
         mUiEventLogger = uiEventLogger;
         mBroadcastDispatcher = broadcastDispatcher;
         mTileServiceRequestController = tileServiceRequestControllerBuilder.create(this);
+        mStatusBarFlags = statusBarFlags;
 
         mInstanceIdSequence = new InstanceIdSequence(MAX_QS_INSTANCE_ID);
         mServices = new TileServices(this, bgLooper, mBroadcastDispatcher, userTracker);
@@ -276,7 +280,7 @@
         if (newValue == null && UserManager.isDeviceInDemoMode(mContext)) {
             newValue = mContext.getResources().getString(R.string.quick_settings_tiles_retail_mode);
         }
-        final List<String> tileSpecs = loadTileSpecs(mContext, newValue, mFeatureFlags);
+        final List<String> tileSpecs = loadTileSpecs(mContext, newValue, mStatusBarFlags);
         int currentUser = mUserTracker.getUserId();
         if (currentUser != mCurrentUser) {
             mUserContext = mUserTracker.getUserContext();
@@ -345,7 +349,7 @@
         if (newTiles.isEmpty() && !tileSpecs.isEmpty()) {
             // If we didn't manage to create any tiles, set it to empty (default)
             Log.d(TAG, "No valid tiles on tuning changed. Setting to default.");
-            changeTiles(currentSpecs, loadTileSpecs(mContext, "", mFeatureFlags));
+            changeTiles(currentSpecs, loadTileSpecs(mContext, "", mStatusBarFlags));
         } else {
             for (int i = 0; i < mCallbacks.size(); i++) {
                 mCallbacks.get(i).onTilesChanged();
@@ -413,7 +417,7 @@
 
     private void changeTileSpecs(Predicate<List<String>> changeFunction) {
         final String setting = mSecureSettings.getStringForUser(TILES_SETTING, mCurrentUser);
-        final List<String> tileSpecs = loadTileSpecs(mContext, setting, mFeatureFlags);
+        final List<String> tileSpecs = loadTileSpecs(mContext, setting, mStatusBarFlags);
         if (changeFunction.test(tileSpecs)) {
             saveTilesToSettings(tileSpecs);
         }
@@ -503,7 +507,7 @@
     }
 
     protected static List<String> loadTileSpecs(
-            Context context, String tileList, FeatureFlags featureFlags) {
+            Context context, String tileList, StatusBarFlags statusBarFlags) {
         final Resources res = context.getResources();
 
         if (TextUtils.isEmpty(tileList)) {
@@ -536,7 +540,7 @@
                 }
             }
         }
-        if (featureFlags.isProviderModelSettingEnabled()) {
+        if (statusBarFlags.isProviderModelSettingEnabled()) {
             if (!tiles.contains("internet")) {
                 if (tiles.contains("wifi")) {
                     // Replace the WiFi with Internet, and remove the Cell
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index 6a57e45..67fdf86 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -30,6 +30,7 @@
 import com.android.systemui.demomode.DemoMode;
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.privacy.OngoingPrivacyChip;
 import com.android.systemui.privacy.PrivacyChipEvent;
@@ -218,7 +219,7 @@
 
         List<String> rssiIgnoredSlots;
 
-        if (mFeatureFlags.isCombinedStatusBarSignalIconsEnabled()) {
+        if (mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)) {
             rssiIgnoredSlots = List.of(
                     getResources().getString(com.android.internal.R.string.status_bar_no_calling),
                     getResources().getString(com.android.internal.R.string.status_bar_call_strength)
@@ -230,7 +231,7 @@
         }
 
         mView.onAttach(mIconManager, mQSExpansionPathInterpolator, rssiIgnoredSlots,
-                mInsetsProvider, mFeatureFlags.useCombinedQSHeaders());
+                mInsetsProvider, mFeatureFlags.isEnabled(Flags.COMBINED_QS_HEADERS));
 
         mDemoModeController.addCallback(mDemoModeReceiver);
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java b/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
deleted file mode 100644
index 8aa2d09..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/SecureSetting.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2014 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.qs;
-
-import android.app.ActivityManager;
-import android.database.ContentObserver;
-import android.os.Handler;
-
-import com.android.systemui.statusbar.policy.Listenable;
-import com.android.systemui.util.settings.SecureSettings;
-
-/** Helper for managing a secure setting. **/
-public abstract class SecureSetting extends ContentObserver implements Listenable {
-    private final SecureSettings mSecureSettings;
-    private final String mSettingName;
-    private final int mDefaultValue;
-
-    private boolean mListening;
-    private int mUserId;
-    private int mObservedValue;
-
-    protected abstract void handleValueChanged(int value, boolean observedChange);
-
-    public SecureSetting(SecureSettings secureSettings, Handler handler, String settingName,
-            int userId) {
-        this(secureSettings, handler, settingName, userId, 0);
-    }
-
-    public SecureSetting(SecureSettings secureSetting, Handler handler, String settingName) {
-        this(secureSetting, handler, settingName, ActivityManager.getCurrentUser());
-    }
-
-    public SecureSetting(SecureSettings secureSettings, Handler handler, String settingName,
-            int userId, int defaultValue) {
-        super(handler);
-        mSecureSettings = secureSettings;
-        mSettingName = settingName;
-        mObservedValue = mDefaultValue = defaultValue;
-        mUserId = userId;
-    }
-
-    public int getValue() {
-        return mSecureSettings.getIntForUser(mSettingName, mDefaultValue, mUserId);
-    }
-
-    public void setValue(int value) {
-        mSecureSettings.putIntForUser(mSettingName, value, mUserId);
-    }
-
-    @Override
-    public void setListening(boolean listening) {
-        if (listening == mListening) return;
-        mListening = listening;
-        if (listening) {
-            mObservedValue = getValue();
-            mSecureSettings.registerContentObserverForUser(
-                    mSecureSettings.getUriFor(mSettingName), false, this, mUserId);
-        } else {
-            mSecureSettings.unregisterContentObserver(this);
-            mObservedValue = mDefaultValue;
-        }
-    }
-
-    @Override
-    public void onChange(boolean selfChange) {
-        final int value = getValue();
-        handleValueChanged(value, value != mObservedValue);
-        mObservedValue = value;
-    }
-
-    public void setUserId(int userId) {
-        mUserId = userId;
-        if (mListening) {
-            setListening(false);
-            setListening(true);
-        }
-    }
-
-    public int getCurrentUser() {
-        return mUserId;
-    }
-
-    public String getKey() {
-        return mSettingName;
-    }
-
-    public boolean isListening() {
-        return mListening;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SettingObserver.java b/packages/SystemUI/src/com/android/systemui/qs/SettingObserver.java
new file mode 100644
index 0000000..6b0abd4
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/SettingObserver.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2014 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.qs;
+
+import android.app.ActivityManager;
+import android.database.ContentObserver;
+import android.os.Handler;
+
+import com.android.systemui.statusbar.policy.Listenable;
+import com.android.systemui.util.settings.GlobalSettings;
+import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.settings.SettingsProxy;
+import com.android.systemui.util.settings.SystemSettings;
+
+/**
+ * Helper for managing secure, global, and system settings through use of {@link SettingsProxy},
+ * which is the common superclass of {@link SecureSettings}, {@link GlobalSettings}, and
+ * {@link SystemSettings}.
+ */
+public abstract class SettingObserver extends ContentObserver implements Listenable {
+    private final SettingsProxy mSettingsProxy;
+    private final String mSettingName;
+    private final int mDefaultValue;
+
+    private boolean mListening;
+    private int mUserId;
+    private int mObservedValue;
+
+    protected abstract void handleValueChanged(int value, boolean observedChange);
+
+    public SettingObserver(SettingsProxy settingsProxy, Handler handler, String settingName,
+            int userId) {
+        this(settingsProxy, handler, settingName, userId, 0);
+    }
+
+    public SettingObserver(SettingsProxy settingsProxy, Handler handler, String settingName) {
+        this(settingsProxy, handler, settingName, ActivityManager.getCurrentUser());
+    }
+
+    public SettingObserver(SettingsProxy settingsProxy, Handler handler, String settingName,
+            int userId, int defaultValue) {
+        super(handler);
+        mSettingsProxy = settingsProxy;
+        mSettingName = settingName;
+        mObservedValue = mDefaultValue = defaultValue;
+        mUserId = userId;
+    }
+
+    public int getValue() {
+        return mListening ? mObservedValue : getValueFromProvider();
+    }
+
+    /**
+     * Set the value of the observed setting.
+     *
+     * @param value The new value for the setting.
+     */
+    public void setValue(int value) {
+        mSettingsProxy.putIntForUser(mSettingName, value, mUserId);
+    }
+
+    private int getValueFromProvider() {
+        return mSettingsProxy.getIntForUser(mSettingName, mDefaultValue, mUserId);
+    }
+
+    @Override
+    public void setListening(boolean listening) {
+        if (listening == mListening) return;
+        mListening = listening;
+        if (listening) {
+            mObservedValue = getValueFromProvider();
+            mSettingsProxy.registerContentObserverForUser(
+                    mSettingsProxy.getUriFor(mSettingName), false, this, mUserId);
+        } else {
+            mSettingsProxy.unregisterContentObserver(this);
+            mObservedValue = mDefaultValue;
+        }
+    }
+
+    @Override
+    public void onChange(boolean selfChange) {
+        final int value = getValueFromProvider();
+        final boolean changed = value != mObservedValue;
+        mObservedValue = value;
+        handleValueChanged(value, changed);
+    }
+
+    /**
+     * Set user handle for which to observe the setting.
+     */
+    public void setUserId(int userId) {
+        mUserId = userId;
+        if (mListening) {
+            setListening(false);
+            setListening(true);
+        }
+    }
+
+    public int getCurrentUser() {
+        return mUserId;
+    }
+
+    public String getKey() {
+        return mSettingName;
+    }
+
+    public boolean isListening() {
+        return mListening;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
index 141c246..4b705ad 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
@@ -42,6 +42,7 @@
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.connectivity.IconState;
 import com.android.systemui.statusbar.connectivity.MobileDataIndicators;
@@ -219,7 +220,7 @@
             CarrierConfigTracker carrierConfigTracker, FeatureFlags featureFlags,
             SlotIndexResolver slotIndexResolver) {
 
-        if (featureFlags.isCombinedStatusBarSignalIconsEnabled()) {
+        if (featureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)) {
             mProviderModel = true;
         } else {
             mProviderModel = false;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 993bbd0..7e410d0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -34,7 +34,6 @@
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.plugins.qs.QSTile.State;
 import com.android.systemui.qs.QSTileHost;
@@ -42,6 +41,7 @@
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.connectivity.StatusBarFlags;
 import com.android.systemui.util.leak.GarbageMonitor;
 
 import java.util.ArrayList;
@@ -63,7 +63,7 @@
     private final Executor mBgExecutor;
     private final Context mContext;
     private final UserTracker mUserTracker;
-    private final FeatureFlags mFeatureFlags;
+    private final StatusBarFlags mStatusBarFlags;
     private TileStateListener mListener;
 
     private boolean mFinished;
@@ -74,13 +74,13 @@
             UserTracker userTracker,
             @Main Executor mainExecutor,
             @Background Executor bgExecutor,
-            FeatureFlags featureFlags
+            StatusBarFlags statusBarFlags
     ) {
         mContext = context;
         mMainExecutor = mainExecutor;
         mBgExecutor = bgExecutor;
         mUserTracker = userTracker;
-        mFeatureFlags = featureFlags;
+        mStatusBarFlags = statusBarFlags;
     }
 
     public void setListener(TileStateListener listener) {
@@ -121,7 +121,7 @@
         }
 
         final ArrayList<QSTile> tilesToAdd = new ArrayList<>();
-        if (mFeatureFlags.isProviderModelSettingEnabled()) {
+        if (mStatusBarFlags.isProviderModelSettingEnabled()) {
             possibleTiles.remove("cell");
             possibleTiles.remove("wifi");
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java
index 103ac65..a1b617f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFlagsModule.java
@@ -21,6 +21,7 @@
 
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.util.settings.GlobalSettings;
 
 import javax.inject.Named;
@@ -48,7 +49,7 @@
     @SysUISingleton
     @Named(PM_LITE_ENABLED)
     static boolean isPMLiteEnabled(FeatureFlags featureFlags, GlobalSettings globalSettings) {
-        return featureFlags.isPMLiteEnabled()
+        return featureFlags.isEnabled(Flags.POWER_MENU_LITE)
                 && globalSettings.getInt(PM_LITE_SETTING, PM_LITE_SETTING_DEFAULT) != 0;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
index 6d1bbee..48255b5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSModule.java
@@ -34,6 +34,8 @@
 import com.android.systemui.statusbar.policy.DataSaverController;
 import com.android.systemui.statusbar.policy.DeviceControlsController;
 import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.RunningFgsController;
+import com.android.systemui.statusbar.policy.RunningFgsControllerImpl;
 import com.android.systemui.statusbar.policy.WalletController;
 import com.android.systemui.util.settings.SecureSettings;
 
@@ -89,4 +91,9 @@
     /** */
     @Binds
     QSHost provideQsHost(QSTileHost controllerImpl);
+
+    /** */
+    @Binds
+    RunningFgsController provideRunningFgsController(
+            RunningFgsControllerImpl runningFgsController);
 }
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 3e850ab..ac95bf5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -36,6 +36,7 @@
 import com.android.systemui.qs.tiles.DataSaverTile;
 import com.android.systemui.qs.tiles.DeviceControlsTile;
 import com.android.systemui.qs.tiles.DndTile;
+import com.android.systemui.qs.tiles.FgsManagerTile;
 import com.android.systemui.qs.tiles.FlashlightTile;
 import com.android.systemui.qs.tiles.HotspotTile;
 import com.android.systemui.qs.tiles.InternetTile;
@@ -43,6 +44,7 @@
 import com.android.systemui.qs.tiles.MicrophoneToggleTile;
 import com.android.systemui.qs.tiles.NfcTile;
 import com.android.systemui.qs.tiles.NightDisplayTile;
+import com.android.systemui.qs.tiles.OneHandedModeTile;
 import com.android.systemui.qs.tiles.QRCodeScannerTile;
 import com.android.systemui.qs.tiles.QuickAccessWalletTile;
 import com.android.systemui.qs.tiles.ReduceBrightColorsTile;
@@ -92,6 +94,8 @@
     private final Provider<AlarmTile> mAlarmTileProvider;
     private final Provider<QuickAccessWalletTile> mQuickAccessWalletTileProvider;
     private final Provider<QRCodeScannerTile> mQRCodeScannerTileProvider;
+    private final Provider<OneHandedModeTile> mOneHandedModeTileProvider;
+    private final Provider<FgsManagerTile> mFgsManagerTileProvider;
 
     private final Lazy<QSHost> mQsHostLazy;
     private final Provider<CustomTile.Builder> mCustomTileBuilderProvider;
@@ -127,7 +131,9 @@
             Provider<DeviceControlsTile> deviceControlsTileProvider,
             Provider<AlarmTile> alarmTileProvider,
             Provider<QuickAccessWalletTile> quickAccessWalletTileProvider,
-            Provider<QRCodeScannerTile> qrCodeScannerTileProvider) {
+            Provider<QRCodeScannerTile> qrCodeScannerTileProvider,
+            Provider<OneHandedModeTile> oneHandedModeTileProvider,
+            Provider<FgsManagerTile> fgsManagerTileProvider) {
         mQsHostLazy = qsHostLazy;
         mCustomTileBuilderProvider = customTileBuilderProvider;
 
@@ -159,6 +165,8 @@
         mAlarmTileProvider = alarmTileProvider;
         mQuickAccessWalletTileProvider = quickAccessWalletTileProvider;
         mQRCodeScannerTileProvider = qrCodeScannerTileProvider;
+        mOneHandedModeTileProvider = oneHandedModeTileProvider;
+        mFgsManagerTileProvider = fgsManagerTileProvider;
     }
 
     public QSTile createTile(String tileSpec) {
@@ -227,6 +235,10 @@
                 return mQuickAccessWalletTileProvider.get();
             case "qr_code_scanner":
                 return mQRCodeScannerTileProvider.get();
+            case "onehanded":
+                return mOneHandedModeTileProvider.get();
+            case "fgsmanager":
+                return mFgsManagerTileProvider.get();
         }
 
         // Custom tiles
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 25ed2e7..eb74b1b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -247,7 +247,10 @@
         } else {
             measuredHeight
         }
-        bottom = top + (actualHeight * squishinessFraction).toInt()
+        // Limit how much we affect the height, so we don't have rounding artifacts when the tile
+        // is too short.
+        val constrainedSquishiness = 0.1f + squishinessFraction * 0.9f
+        bottom = top + (actualHeight * constrainedSquishiness).toInt()
         scrollY = (actualHeight - height) / 2
     }
 
@@ -648,7 +651,9 @@
         "controls" to R.array.tile_states_controls,
         "wallet" to R.array.tile_states_wallet,
         "qr_code_scanner" to R.array.tile_states_qr_code_scanner,
-        "alarm" to R.array.tile_states_alarm
+        "alarm" to R.array.tile_states_alarm,
+        "onehanded" to R.array.tile_states_onehanded,
+        "fgsmanager" to R.array.tile_states_fgsmanager
     )
 
     fun getSubtitleId(spec: String?): Int {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
index 22cd6f8..5650a17 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/AirplaneModeTile.java
@@ -44,10 +44,11 @@
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.SettingObserver;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.util.settings.GlobalSettings;
 
 import javax.inject.Inject;
 
@@ -56,7 +57,7 @@
 /** Quick settings tile: Airplane mode **/
 public class AirplaneModeTile extends QSTileImpl<BooleanState> {
     private final Icon mIcon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_airplane);
-    private final GlobalSetting mSetting;
+    private final SettingObserver mSetting;
     private final BroadcastDispatcher mBroadcastDispatcher;
     private final Lazy<ConnectivityManager> mLazyConnectivityManager;
 
@@ -73,16 +74,17 @@
             ActivityStarter activityStarter,
             QSLogger qsLogger,
             BroadcastDispatcher broadcastDispatcher,
-            Lazy<ConnectivityManager> lazyConnectivityManager
+            Lazy<ConnectivityManager> lazyConnectivityManager,
+            GlobalSettings globalSettings
     ) {
         super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
                 statusBarStateController, activityStarter, qsLogger);
         mBroadcastDispatcher = broadcastDispatcher;
         mLazyConnectivityManager = lazyConnectivityManager;
 
-        mSetting = new GlobalSetting(mContext, mHandler, Global.AIRPLANE_MODE_ON) {
+        mSetting = new SettingObserver(globalSettings, mHandler, Global.AIRPLANE_MODE_ON) {
             @Override
-            protected void handleValueChanged(int value) {
+            protected void handleValueChanged(int value, boolean observedChange) {
                 // mHandler is the background handler so calling this is OK
                 handleRefreshState(value);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
index e3024fa..b8ef312 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BatterySaverTile.java
@@ -36,7 +36,7 @@
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.SecureSetting;
+import com.android.systemui.qs.SettingObserver;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -49,7 +49,7 @@
 
     private final BatteryController mBatteryController;
     @VisibleForTesting
-    protected final SecureSetting mSetting;
+    protected final SettingObserver mSetting;
 
     private int mLevel;
     private boolean mPowerSave;
@@ -76,7 +76,7 @@
         mBatteryController = batteryController;
         mBatteryController.observe(getLifecycle(), this);
         int currentUser = host.getUserContext().getUserId();
-        mSetting = new SecureSetting(
+        mSetting = new SettingObserver(
                 secureSettings,
                 mHandler,
                 Secure.LOW_POWER_WARNING_ACKNOWLEDGED,
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
index 5e502cc..d2d2180 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java
@@ -17,7 +17,6 @@
 package com.android.systemui.qs.tiles;
 
 import android.content.Intent;
-import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
 import android.provider.Settings;
@@ -39,7 +38,7 @@
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.SecureSetting;
+import com.android.systemui.qs.SettingObserver;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.settings.UserTracker;
@@ -55,7 +54,7 @@
     private static final String COLOR_INVERSION_PREFERENCE_KEY = "toggle_inversion_preference";
 
     private final Icon mIcon = ResourceIcon.get(drawable.ic_invert_colors);
-    private final SecureSetting mSetting;
+    private final SettingObserver mSetting;
 
     private boolean mListening;
 
@@ -75,7 +74,7 @@
         super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
                 statusBarStateController, activityStarter, qsLogger);
 
-        mSetting = new SecureSetting(secureSettings, mHandler,
+        mSetting = new SettingObserver(secureSettings, mHandler,
                 Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, userTracker.getUserId()) {
             @Override
             protected void handleValueChanged(int value, boolean observedChange) {
@@ -110,11 +109,7 @@
 
     @Override
     public Intent getLongClickIntent() {
-        Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
-        Bundle bundle = new Bundle();
-        bundle.putString(EXTRA_FRAGMENT_ARGS_KEY, COLOR_INVERSION_PREFERENCE_KEY);
-        intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGS_KEY, bundle);
-        return intent;
+        return new Intent(Settings.ACTION_COLOR_INVERSION_SETTINGS);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index e896c7c..18b401f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -19,6 +19,7 @@
 import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
 import static android.provider.Settings.Global.ZEN_MODE_OFF;
 
+import android.app.AlertDialog;
 import android.app.Dialog;
 import android.content.Context;
 import android.content.Intent;
@@ -41,7 +42,6 @@
 import android.view.View;
 import android.view.View.OnAttachStateChangeListener;
 import android.view.ViewGroup;
-import android.view.WindowManager;
 import android.widget.Switch;
 import android.widget.Toast;
 
@@ -53,6 +53,7 @@
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.SysUIToast;
+import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
@@ -61,10 +62,12 @@
 import com.android.systemui.plugins.qs.QSTile.BooleanState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.SettingObserver;
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.util.settings.SecureSettings;
 import com.android.systemui.volume.ZenModePanel;
 
 import javax.inject.Inject;
@@ -81,6 +84,8 @@
     private final ZenModeController mController;
     private final DndDetailAdapter mDetailAdapter;
     private final SharedPreferences mSharedPreferences;
+    private final SettingObserver mSettingZenDuration;
+    private final DialogLaunchAnimator mDialogLaunchAnimator;
 
     private boolean mListening;
     private boolean mShowingDetail;
@@ -96,7 +101,9 @@
             ActivityStarter activityStarter,
             QSLogger qsLogger,
             ZenModeController zenModeController,
-            @Main SharedPreferences sharedPreferences
+            @Main SharedPreferences sharedPreferences,
+            SecureSettings secureSettings,
+            DialogLaunchAnimator dialogLaunchAnimator
     ) {
         super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
                 statusBarStateController, activityStarter, qsLogger);
@@ -104,6 +111,14 @@
         mSharedPreferences = sharedPreferences;
         mDetailAdapter = new DndDetailAdapter();
         mController.observe(getLifecycle(), mZenCallback);
+        mDialogLaunchAnimator = dialogLaunchAnimator;
+        mSettingZenDuration = new SettingObserver(secureSettings, mUiHandler,
+                Settings.Secure.ZEN_DURATION, getHost().getUserId()) {
+            @Override
+            protected void handleValueChanged(int value, boolean observedChange) {
+                refreshState();
+            }
+        };
     }
 
     public static void setVisible(Context context, boolean visible) {
@@ -144,14 +159,18 @@
         if (mState.value) {
             mController.setZen(ZEN_MODE_OFF, null, TAG);
         } else {
-            showDetail(true);
+            enableZenMode(view);
         }
     }
 
     @Override
-    public void showDetail(boolean show) {
-        int zenDuration = Settings.Secure.getInt(mContext.getContentResolver(),
-                Settings.Secure.ZEN_DURATION, 0);
+    protected void handleUserSwitch(int newUserId) {
+        super.handleUserSwitch(newUserId);
+        mSettingZenDuration.setUserId(newUserId);
+    }
+
+    private void enableZenMode(@Nullable View view) {
+        int zenDuration = mSettingZenDuration.getValue();
         boolean showOnboarding = Settings.Secure.getInt(mContext.getContentResolver(),
                 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
                 && Settings.Secure.getInt(mContext.getContentResolver(),
@@ -170,14 +189,17 @@
             switch (zenDuration) {
                 case Settings.Secure.ZEN_DURATION_PROMPT:
                     mUiHandler.post(() -> {
-                        Dialog mDialog = new EnableZenModeDialog(mContext).createDialog();
-                        mDialog.getWindow().setType(
-                                WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-                        SystemUIDialog.setShowForAllUsers(mDialog, true);
-                        SystemUIDialog.registerDismissListener(mDialog);
-                        SystemUIDialog.setWindowOnTop(mDialog);
-                        mUiHandler.post(() -> mDialog.show());
-                        mHost.collapsePanels();
+                        Dialog dialog = makeZenModeDialog();
+                        if (view != null) {
+                            final Dialog hostDialog =
+                                    mDialogLaunchAnimator.showFromView(dialog, view, false);
+                            setDialogListeners(dialog, hostDialog);
+                        } else {
+                            // If we are not launching with animator, register default
+                            // dismiss listener
+                            SystemUIDialog.registerDismissListener(dialog);
+                            dialog.show();
+                        }
                     });
                     break;
                 case Settings.Secure.ZEN_DURATION_FOREVER:
@@ -192,6 +214,20 @@
         }
     }
 
+    private Dialog makeZenModeDialog() {
+        AlertDialog dialog = new EnableZenModeDialog(mContext, R.style.Theme_SystemUI_Dialog)
+                .createDialog();
+        SystemUIDialog.applyFlags(dialog);
+        SystemUIDialog.setShowForAllUsers(dialog, true);
+        return dialog;
+    }
+
+    private void setDialogListeners(Dialog zenModeDialog, Dialog hostDialog) {
+        // Zen mode dialog is never hidden.
+        SystemUIDialog.registerDismissListener(zenModeDialog, hostDialog::dismiss);
+        zenModeDialog.setOnCancelListener(dialog -> hostDialog.cancel());
+    }
+
     @Override
     protected void handleSecondaryClick(@Nullable View view) {
         if (mController.isVolumeRestricted()) {
@@ -270,6 +306,8 @@
         state.dualLabelContentDescription = mContext.getResources().getString(
                 R.string.accessibility_quick_settings_open_settings, getTileLabel());
         state.expandedAccessibilityClassName = Switch.class.getName();
+        state.forceExpandIcon =
+                mSettingZenDuration.getValue() == Settings.Secure.ZEN_DURATION_PROMPT;
     }
 
     @Override
@@ -296,6 +334,13 @@
         } else {
             Prefs.unregisterListener(mContext, mPrefListener);
         }
+        mSettingZenDuration.setListening(listening);
+    }
+
+    @Override
+    protected void handleDestroy() {
+        super.handleDestroy();
+        mSettingZenDuration.setListening(false);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt
new file mode 100644
index 0000000..75cf4d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/FgsManagerTile.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 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.qs.tiles
+
+import android.content.Intent
+import android.os.Handler
+import android.os.Looper
+import android.provider.DeviceConfig
+import android.view.View
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags
+import com.android.internal.logging.MetricsLogger
+import com.android.systemui.DejankUtils
+import com.android.systemui.R
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.fgsmanager.FgsManagerDialogFactory
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.qs.QSHost
+import com.android.systemui.qs.logging.QSLogger
+import com.android.systemui.qs.tileimpl.QSTileImpl
+import com.android.systemui.statusbar.policy.RunningFgsController
+import com.android.systemui.statusbar.policy.RunningFgsController.UserPackageTime
+import java.util.concurrent.Executor
+import javax.inject.Inject
+
+/**
+ * Quicksettings tile for the foreground services manager (task manager)
+ */
+class FgsManagerTile @Inject constructor(
+    host: QSHost?,
+    @Background backgroundLooper: Looper?,
+    @Background private val backgroundExecutor: Executor?,
+    @Main mainHandler: Handler?,
+    falsingManager: FalsingManager?,
+    metricsLogger: MetricsLogger?,
+    statusBarStateController: StatusBarStateController?,
+    activityStarter: ActivityStarter?,
+    qsLogger: QSLogger?,
+    private val fgsManagerDialogFactory: FgsManagerDialogFactory,
+    private val runningFgsController: RunningFgsController
+) : QSTileImpl<QSTile.State?>(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
+        statusBarStateController, activityStarter, qsLogger), RunningFgsController.Callback {
+
+    override fun handleInitialize() {
+        super.handleInitialize()
+        mUiHandler.post { runningFgsController.observe(lifecycle, this) }
+    }
+
+    override fun isAvailable(): Boolean {
+        return DejankUtils.whitelistIpcs<Boolean> {
+            DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_SYSTEMUI,
+                    SystemUiDeviceConfigFlags.TASK_MANAGER_ENABLED, false)
+        }
+    }
+
+    override fun newTileState(): QSTile.State {
+        return QSTile.State()
+    }
+
+    override fun handleClick(view: View?) {
+        mUiHandler.post { fgsManagerDialogFactory.create(view) }
+    }
+
+    override fun handleUpdateState(state: QSTile.State?, arg: Any?) {
+        state?.label = tileLabel
+        state?.secondaryLabel = runningFgsController.getPackagesWithFgs().size.toString()
+        state?.handlesLongClick = false
+        state?.icon = ResourceIcon.get(R.drawable.ic_list)
+    }
+
+    override fun getMetricsCategory(): Int = 0
+
+    override fun getLongClickIntent(): Intent? = null
+
+    // Inline the string so we don't waste translator time since this isn't used in the mocks.
+    // TODO If mocks change need to remember to move this to strings.xml
+    override fun getTileLabel(): CharSequence = "Active apps"
+
+    override fun onFgsPackagesChanged(packages: List<UserPackageTime>) = refreshState()
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java
new file mode 100644
index 0000000..7e17124
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/OneHandedModeTile.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2021 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.qs.tiles;
+
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.provider.Settings;
+import android.service.quicksettings.Tile;
+import android.view.View;
+import android.widget.Switch;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.qs.QSTile.BooleanState;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.SettingObserver;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
+import com.android.wm.shell.onehanded.OneHanded;
+
+import javax.inject.Inject;
+
+/** Quick settings tile: One-handed mode **/
+public class OneHandedModeTile extends QSTileImpl<BooleanState> {
+    private final Icon mIcon = ResourceIcon.get(
+            com.android.internal.R.drawable.ic_qs_one_handed_mode);
+    private final SettingObserver mSetting;
+
+    @Inject
+    public OneHandedModeTile(
+            QSHost host,
+            @Background Looper backgroundLooper,
+            @Main Handler mainHandler,
+            FalsingManager falsingManager,
+            MetricsLogger metricsLogger,
+            StatusBarStateController statusBarStateController,
+            ActivityStarter activityStarter,
+            QSLogger qsLogger,
+            UserTracker userTracker,
+            SecureSettings secureSettings) {
+        super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger,
+                statusBarStateController, activityStarter, qsLogger);
+        mSetting = new SettingObserver(secureSettings, mHandler,
+                Settings.Secure.ONE_HANDED_MODE_ENABLED, userTracker.getUserId()) {
+            @Override
+            protected void handleValueChanged(int value, boolean observedChange) {
+                // mHandler is the background handler so calling this is OK
+                handleRefreshState(value);
+            }
+        };
+    }
+
+    @Override
+    public boolean isAvailable() {
+        return isSupportOneHandedMode();
+    }
+
+    @Override
+    protected void handleDestroy() {
+        super.handleDestroy();
+        mSetting.setListening(false);
+    }
+
+    @Override
+    public BooleanState newTileState() {
+        return new BooleanState();
+    }
+
+    @Override
+    public void handleSetListening(boolean listening) {
+        super.handleSetListening(listening);
+        mSetting.setListening(listening);
+    }
+
+    @Override
+    protected void handleUserSwitch(int newUserId) {
+        mSetting.setUserId(newUserId);
+        handleRefreshState(mSetting.getValue());
+    }
+
+    @Override
+    public Intent getLongClickIntent() {
+        return new Intent(Settings.ACTION_ONE_HANDED_SETTINGS);
+    }
+
+    @Override
+    protected void handleClick(@Nullable View view) {
+        mSetting.setValue(mState.value ? 0 : 1);
+    }
+
+    @Override
+    public CharSequence getTileLabel() {
+        return mContext.getString(R.string.quick_settings_onehanded_label);
+    }
+
+    @Override
+    protected void handleUpdateState(BooleanState state, Object arg) {
+        final int value = arg instanceof Integer ? (Integer) arg : mSetting.getValue();
+        final boolean enabled = value != 0;
+        state.value = enabled;
+        state.label = mContext.getString(R.string.quick_settings_onehanded_label);
+        state.icon = mIcon;
+        if (state.slash == null) {
+            state.slash = new SlashState();
+        }
+        state.slash.isSlashed = !state.value;
+        state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE;
+        state.contentDescription = state.label;
+        state.expandedAccessibilityClassName = Switch.class.getName();
+    }
+
+    @Override
+    public int getMetricsCategory() {
+        // MetricsProto/MetricsEvent is deprecated, and QSTileImpl has code to log events to Tron,
+        // as well as UiEventLogger, so just simply return 0 here.
+        return 0;
+    }
+
+    @VisibleForTesting
+    public boolean isSupportOneHandedMode() {
+        return OneHanded.sIsSupportOneHandedMode;
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index b718ebf..f793a50 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -29,6 +29,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import androidx.annotation.Nullable;
+
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -38,10 +40,10 @@
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.qs.PseudoGridView;
 import com.android.systemui.qs.QSUserSwitcherEvent;
+import com.android.systemui.qs.user.UserSwitchDialogController;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 
-import java.util.function.Consumer;
-
 import javax.inject.Inject;
 
 /**
@@ -78,7 +80,7 @@
         private View mCurrentUserView;
         private final UiEventLogger mUiEventLogger;
         private final FalsingManager mFalsingManager;
-        private Consumer<UserSwitcherController.UserRecord> mClickCallback;
+        private @Nullable UserSwitchDialogController.DialogShower mDialogShower;
 
         @Inject
         public Adapter(Context context, UserSwitcherController controller,
@@ -96,8 +98,17 @@
             return createUserDetailItemView(convertView, parent, item);
         }
 
-        public void injectCallback(Consumer<UserSwitcherController.UserRecord> clickCallback) {
-            mClickCallback = clickCallback;
+        /**
+         * If this adapter is inside a dialog, passing a
+         * {@link UserSwitchDialogController.DialogShower} will help animate to and from the parent
+         * dialog. This will also allow for dismissing the whole stack of dialogs in a single
+         * animation.
+         *
+         * @param shower
+         * @see SystemUIDialog#dismissStack()
+         */
+        public void injectDialogShower(UserSwitchDialogController.DialogShower shower) {
+            mDialogShower = shower;
         }
 
         public UserDetailItemView createUserDetailItemView(View convertView, ViewGroup parent,
@@ -174,12 +185,9 @@
                     }
                     view.setActivated(true);
                 }
-                onUserListItemClicked(tag);
+                onUserListItemClicked(tag, mDialogShower);
             }
             Trace.endSection();
-            if (mClickCallback != null) {
-                mClickCallback.accept(tag);
-            }
         }
 
         public void linkToViewGroup(ViewGroup viewGroup) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 563c4cd..033fe1e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -56,6 +56,7 @@
 
 import com.android.internal.logging.UiEvent;
 import com.android.internal.logging.UiEventLogger;
+import com.android.settingslib.Utils;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
 import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan;
@@ -120,6 +121,7 @@
     private TextView mMobileTitleText;
     private TextView mMobileSummaryText;
     private Switch mMobileDataToggle;
+    private View mMobileToggleDivider;
     private Switch mWiFiToggle;
     private FrameLayout mDoneLayout;
     private Drawable mBackgroundOn;
@@ -128,6 +130,7 @@
     private boolean mCanConfigMobileData;
 
     // Wi-Fi entries
+    private int mWifiNetworkHeight;
     @VisibleForTesting
     protected WifiEntry mConnectedWifiEntry;
     @VisibleForTesting
@@ -185,6 +188,9 @@
 
         window.setWindowAnimations(R.style.Animation_InternetDialog);
 
+        mWifiNetworkHeight = mContext.getResources()
+                .getDimensionPixelSize(R.dimen.internet_dialog_wifi_network_height);
+
         mInternetDialogLayout = mDialogView.requireViewById(R.id.internet_connectivity_dialog);
         mInternetDialogTitle = mDialogView.requireViewById(R.id.internet_dialog_title);
         mInternetDialogSubTitle = mDialogView.requireViewById(R.id.internet_dialog_subtitle);
@@ -207,6 +213,7 @@
         mSignalIcon = mDialogView.requireViewById(R.id.signal_icon);
         mMobileTitleText = mDialogView.requireViewById(R.id.mobile_title);
         mMobileSummaryText = mDialogView.requireViewById(R.id.mobile_summary);
+        mMobileToggleDivider = mDialogView.requireViewById(R.id.mobile_toggle_divider);
         mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_toggle);
         mWiFiToggle = mDialogView.requireViewById(R.id.wifi_toggle);
         mBackgroundOn = mContext.getDrawable(R.drawable.settingslib_switch_bar_bg_on);
@@ -306,12 +313,8 @@
         final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled();
         updateWifiToggle(isWifiEnabled, isDeviceLocked);
         updateConnectedWifi(isWifiEnabled, isDeviceLocked);
+        updateWifiListAndSeeAll(isWifiEnabled, isDeviceLocked);
         updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked);
-
-        final int visibility = (isDeviceLocked || !isWifiEnabled || mWifiEntriesCount <= 0)
-                ? View.GONE : View.VISIBLE;
-        mWifiRecyclerView.setVisibility(visibility);
-        mSeeAllLayout.setVisibility(visibility);
     }
 
     private void setOnClickListener() {
@@ -336,9 +339,6 @@
         mSeeAllLayout.setOnClickListener(v -> onClickSeeMoreButton());
         mWiFiToggle.setOnCheckedChangeListener(
                 (buttonView, isChecked) -> {
-                    if (isChecked) {
-                        mWifiScanNotifyLayout.setVisibility(View.GONE);
-                    }
                     buttonView.setChecked(isChecked);
                     mWifiManager.setWifiEnabled(isChecked);
                 });
@@ -382,7 +382,17 @@
             mMobileNetworkLayout.setBackground(
                     isCarrierNetworkConnected ? mBackgroundOn : mBackgroundOff);
 
+            TypedArray array = mContext.obtainStyledAttributes(
+                    R.style.InternetDialog_Divider_Active, new int[]{android.R.attr.background});
+            int dividerColor = Utils.getColorAttrDefaultColor(mContext,
+                    android.R.attr.textColorSecondary);
+            mMobileToggleDivider.setBackgroundColor(isCarrierNetworkConnected
+                    ? array.getColor(0, dividerColor) : dividerColor);
+            array.recycle();
+
             mMobileDataToggle.setVisibility(mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE);
+            mMobileToggleDivider.setVisibility(
+                    mCanConfigMobileData ? View.VISIBLE : View.INVISIBLE);
         }
     }
 
@@ -414,6 +424,35 @@
     }
 
     @MainThread
+    private void updateWifiListAndSeeAll(boolean isWifiEnabled, boolean isDeviceLocked) {
+        if (!isWifiEnabled || isDeviceLocked) {
+            mWifiRecyclerView.setVisibility(View.GONE);
+            mSeeAllLayout.setVisibility(View.GONE);
+            return;
+        }
+        mWifiRecyclerView.setMinimumHeight(mWifiNetworkHeight * getWifiListMaxCount());
+        mWifiRecyclerView.setVisibility(View.VISIBLE);
+        final boolean showSeeAll = mConnectedWifiEntry != null || mWifiEntriesCount > 0;
+        mSeeAllLayout.setVisibility(showSeeAll ? View.VISIBLE : View.INVISIBLE);
+    }
+
+    @VisibleForTesting
+    @MainThread
+    int getWifiListMaxCount() {
+        int count = InternetDialogController.MAX_WIFI_ENTRY_COUNT;
+        if (mEthernetLayout.getVisibility() == View.VISIBLE) {
+            count -= 1;
+        }
+        if (mMobileNetworkLayout.getVisibility() == View.VISIBLE) {
+            count -= 1;
+        }
+        if (mConnectedWifListLayout.getVisibility() == View.VISIBLE) {
+            count -= 1;
+        }
+        return count;
+    }
+
+    @MainThread
     private void updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled,
             boolean isDeviceLocked) {
         if (isWifiEnabled || !isWifiScanEnabled || isDeviceLocked) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index 1c8bd78..2a7d2c3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -1077,6 +1077,9 @@
         params.width = WindowManager.LayoutParams.WRAP_CONTENT;
         params.format = PixelFormat.TRANSLUCENT;
         params.type = WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
+        params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+                | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
         params.y = systemUIToast.getYOffset();
 
         int absGravity = Gravity.getAbsoluteGravity(systemUIToast.getGravity(),
diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
deleted file mode 100644
index 26d1bbd..0000000
--- a/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2021 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.qs.user
-
-import android.content.Context
-import android.os.Bundle
-import android.view.Gravity
-import android.view.View
-import android.view.ViewGroup
-import android.view.WindowInsets
-import android.view.WindowManager
-import com.android.systemui.qs.PseudoGridView
-import com.android.systemui.statusbar.phone.SystemUIDialog
-import com.android.systemui.R
-
-/**
- * Dialog for switching users or creating new ones.
- */
-class UserDialog(
-    context: Context
-) : SystemUIDialog(context) {
-
-    // create() is no-op after creation
-    private lateinit var _doneButton: View
-    /**
-     * Button with text "Done" in dialog.
-     */
-    val doneButton: View
-        get() {
-            create()
-            return _doneButton
-        }
-
-    private lateinit var _settingsButton: View
-    /**
-     * Button with text "User Settings" in dialog.
-     */
-    val settingsButton: View
-        get() {
-            create()
-            return _settingsButton
-        }
-
-    private lateinit var _grid: PseudoGridView
-    /**
-     * Grid to populate with user avatar from adapter
-     */
-    val grid: ViewGroup
-        get() {
-            create()
-            return _grid
-        }
-
-    override fun onCreate(savedInstanceState: Bundle?) {
-        super.onCreate(savedInstanceState)
-        window?.apply {
-            setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL)
-            attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars()
-            attributes.receiveInsetsIgnoringZOrder = true
-            setGravity(Gravity.CENTER)
-        }
-        setContentView(R.layout.qs_user_dialog_content)
-
-        _doneButton = requireViewById(R.id.done)
-        _settingsButton = requireViewById(R.id.settings)
-        _grid = requireViewById(R.id.grid)
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
index bae7996..00e0454 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/user/UserSwitchDialogController.kt
@@ -16,16 +16,21 @@
 
 package com.android.systemui.qs.user
 
+import android.app.Dialog
 import android.content.Context
+import android.content.DialogInterface
 import android.content.Intent
 import android.provider.Settings
+import android.view.LayoutInflater
 import android.view.View
 import androidx.annotation.VisibleForTesting
+import com.android.systemui.R
 import com.android.systemui.animation.DialogLaunchAnimator
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.qs.tiles.UserDetailView
+import com.android.systemui.statusbar.phone.SystemUIDialog
 import javax.inject.Inject
 import javax.inject.Provider
 
@@ -38,7 +43,7 @@
     private val activityStarter: ActivityStarter,
     private val falsingManager: FalsingManager,
     private val dialogLaunchAnimator: DialogLaunchAnimator,
-    private val dialogFactory: (Context) -> UserDialog
+    private val dialogFactory: (Context) -> SystemUIDialog
 ) {
 
     @Inject
@@ -52,7 +57,7 @@
         activityStarter,
         falsingManager,
         dialogLaunchAnimator,
-        { UserDialog(it) }
+        { SystemUIDialog(it) }
     )
 
     companion object {
@@ -69,9 +74,10 @@
         with(dialogFactory(view.context)) {
             setShowForAllUsers(true)
             setCanceledOnTouchOutside(true)
-            create() // Needs to be called before we can retrieve views
 
-            settingsButton.setOnClickListener {
+            setTitle(R.string.qs_user_switch_dialog_title)
+            setPositiveButton(R.string.quick_settings_done, null)
+            setNeutralButton(R.string.quick_settings_more_user_settings) { _, _ ->
                 if (!falsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) {
                     dialogLaunchAnimator.disableAllCurrentDialogsExitAnimations()
                     activityStarter.postStartActivityDismissingKeyguard(
@@ -79,17 +85,33 @@
                         0
                     )
                 }
-                dismiss()
             }
-            doneButton.setOnClickListener { dismiss() }
+            val gridFrame = LayoutInflater.from(this.context)
+                .inflate(R.layout.qs_user_dialog_content, null)
+            setView(gridFrame)
 
             val adapter = userDetailViewAdapterProvider.get()
-            adapter.injectCallback {
-                dismiss()
-            }
-            adapter.linkToViewGroup(grid)
 
-            dialogLaunchAnimator.showFromView(this, view)
+            adapter.linkToViewGroup(gridFrame.findViewById(R.id.grid))
+
+            val hostDialog = dialogLaunchAnimator.showFromView(this, view)
+            adapter.injectDialogShower(DialogShowerImpl(hostDialog, dialogLaunchAnimator))
         }
     }
+
+    private class DialogShowerImpl(
+        private val hostDialog: Dialog,
+        private val dialogLaunchAnimator: DialogLaunchAnimator
+    ) : DialogInterface by hostDialog, DialogShower {
+        override fun showDialog(dialog: Dialog): Dialog {
+            return dialogLaunchAnimator.showFromDialog(
+                dialog,
+                parentHostDialog = hostDialog
+            )
+        }
+    }
+
+    interface DialogShower : DialogInterface {
+        fun showDialog(dialog: Dialog): Dialog
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index fa874b1..3ed7e84 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -986,6 +986,18 @@
         }
     }
 
+    public void onNavButtonsDarkIntensityChanged(float darkIntensity) {
+        try {
+            if (mOverviewProxy != null) {
+                mOverviewProxy.onNavButtonsDarkIntensityChanged(darkIntensity);
+            } else {
+                Log.e(TAG_OPS, "Failed to get overview proxy to update nav buttons dark intensity");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG_OPS, "Failed to call onNavButtonsDarkIntensityChanged()", e);
+        }
+    }
+
     private void updateEnabledState() {
         final int currentUser = ActivityManagerWrapper.getInstance().getCurrentUserId();
         mIsEnabled = mContext.getPackageManager().resolveServiceAsUser(mQuickStepIntent,
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
index a7f8bca..7bcaf5f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotView.java
@@ -86,6 +86,7 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.R;
 import com.android.systemui.screenshot.ScreenshotController.SavedImageData.ActionTransition;
+import com.android.systemui.shared.system.InputChannelCompat;
 import com.android.systemui.shared.system.InputMonitorCompat;
 import com.android.systemui.shared.system.QuickStepContract;
 
@@ -162,6 +163,7 @@
     private GestureDetector mSwipeDetector;
     private SwipeDismissHandler mSwipeDismissHandler;
     private InputMonitorCompat mInputMonitor;
+    private InputChannelCompat.InputEventReceiver mInputEventReceiver;
     private boolean mShowScrollablePreview;
     private String mPackageName = "";
 
@@ -302,8 +304,8 @@
     private void startInputListening() {
         stopInputListening();
         mInputMonitor = new InputMonitorCompat("Screenshot", Display.DEFAULT_DISPLAY);
-        mInputMonitor.getInputReceiver(Looper.getMainLooper(), Choreographer.getInstance(),
-                ev -> {
+        mInputEventReceiver = mInputMonitor.getInputReceiver(
+                Looper.getMainLooper(), Choreographer.getInstance(), ev -> {
                     if (ev instanceof MotionEvent) {
                         MotionEvent event = (MotionEvent) ev;
                         if (event.getActionMasked() == MotionEvent.ACTION_DOWN
@@ -320,6 +322,10 @@
             mInputMonitor.dispose();
             mInputMonitor = null;
         }
+        if (mInputEventReceiver != null) {
+            mInputEventReceiver.dispose();
+            mInputEventReceiver = null;
+        }
     }
 
     @Override // ViewGroup
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 75b3592..3cecbb7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -533,9 +533,13 @@
      * @param animate {@code true} to show animations.
      */
     public void recomputeDisableFlags(int displayId, boolean animate) {
-        int disabled1 = getDisabled1(displayId);
-        int disabled2 = getDisabled2(displayId);
-        disable(displayId, disabled1, disabled2, animate);
+        // This must update holding the lock otherwise it can clobber the disabled flags set on the
+        // binder thread from the disable() call
+        synchronized (mLock) {
+            int disabled1 = getDisabled1(displayId);
+            int disabled2 = getDisabled2(displayId);
+            disable(displayId, disabled1, disabled2, animate);
+        }
     }
 
     private void setDisabled(int displayId, int disabled1, int disabled2) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index ed36a27..f23a7ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -138,6 +138,7 @@
 
     private boolean mPowerPluggedIn;
     private boolean mPowerPluggedInWired;
+    private boolean mPowerPluggedInWireless;
     private boolean mPowerCharged;
     private boolean mBatteryOverheated;
     private boolean mEnableBatteryDefender;
@@ -716,6 +717,9 @@
                                         textView.setTranslationY(BOUNCE_ANIMATION_FINAL_Y);
                                         ViewClippingUtil.setClippingDeactivated(textView, false,
                                                 mClippingParams);
+                                        // Unset the listener, otherwise this may persist for
+                                        // another view property animation
+                                        textView.animate().setListener(null);
                                     }
                                 });
                     }
@@ -751,10 +755,14 @@
                             : R.string.keyguard_plugged_in;
                     break;
             }
-        } else {
+        } else if (mPowerPluggedInWireless) {
             chargingId = hasChargingTime
                     ? R.string.keyguard_indication_charging_time_wireless
                     : R.string.keyguard_plugged_in_wireless;
+        } else {
+            chargingId = hasChargingTime
+                    ? R.string.keyguard_indication_charging_time
+                    : R.string.keyguard_plugged_in;
         }
 
         String percentage = NumberFormat.getPercentInstance().format(mBatteryLevel / 100f);
@@ -866,6 +874,7 @@
                     || status.status == BatteryManager.BATTERY_STATUS_FULL;
             boolean wasPluggedIn = mPowerPluggedIn;
             mPowerPluggedInWired = status.isPluggedInWired() && isChargingOrFull;
+            mPowerPluggedInWireless = status.isPluggedInWireless() && isChargingOrFull;
             mPowerPluggedIn = status.isPluggedIn() && isChargingOrFull;
             mPowerCharged = status.isCharged();
             mChargingWattage = status.maxChargingWattage;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 7cfa830..efe02ad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -33,11 +33,9 @@
 import android.media.MediaMetadata;
 import android.media.session.MediaController;
 import android.media.session.MediaSession;
-import android.media.session.MediaSessionManager;
 import android.media.session.PlaybackState;
 import android.os.AsyncTask;
 import android.os.Trace;
-import android.os.UserHandle;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationStats;
 import android.service.notification.StatusBarNotification;
@@ -53,12 +51,12 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.media.MediaData;
 import com.android.systemui.media.MediaDataManager;
 import com.android.systemui.media.SmartspaceMediaData;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.dagger.StatusBarModule;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
@@ -83,7 +81,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
@@ -133,7 +130,6 @@
     private final DelayableExecutor mMainExecutor;
 
     private final Context mContext;
-    private final MediaSessionManager mMediaSessionManager;
     private final ArrayList<MediaListener> mMediaListeners;
     private final Lazy<Optional<StatusBar>> mStatusBarOptionalLazy;
     private final MediaArtworkProcessor mMediaArtworkProcessor;
@@ -188,7 +184,7 @@
             KeyguardBypassController keyguardBypassController,
             NotifPipeline notifPipeline,
             NotifCollection notifCollection,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             @Main DelayableExecutor mainExecutor,
             MediaDataManager mediaDataManager,
             DumpManager dumpManager) {
@@ -196,10 +192,6 @@
         mMediaArtworkProcessor = mediaArtworkProcessor;
         mKeyguardBypassController = keyguardBypassController;
         mMediaListeners = new ArrayList<>();
-        // TODO: use MediaSessionManager.SessionListener to hook us up to future updates
-        // in session state
-        mMediaSessionManager = (MediaSessionManager) mContext.getSystemService(
-                Context.MEDIA_SESSION_SERVICE);
         // TODO: use KeyguardStateController#isOccluded to remove this dependency
         mStatusBarOptionalLazy = statusBarOptionalLazy;
         mNotificationShadeWindowController = notificationShadeWindowController;
@@ -210,7 +202,7 @@
         mNotifPipeline = notifPipeline;
         mNotifCollection = notifCollection;
 
-        if (!featureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (!notifPipelineFlags.isNewPipelineEnabled()) {
             setupNEM();
             mUsingNotifPipeline = false;
         } else {
@@ -457,7 +449,8 @@
         NotificationEntry mediaNotification = null;
         MediaController controller = null;
         for (NotificationEntry entry : allNotifications) {
-            if (entry.isMediaNotification()) {
+            Notification notif = entry.getSbn().getNotification();
+            if (notif.isMediaNotification()) {
                 final MediaSession.Token token =
                         entry.getSbn().getNotification().extras.getParcelable(
                                 Notification.EXTRA_MEDIA_SESSION);
@@ -476,35 +469,6 @@
                 }
             }
         }
-        if (mediaNotification == null) {
-            // Still nothing? OK, let's just look for live media sessions and see if they match
-            // one of our notifications. This will catch apps that aren't (yet!) using media
-            // notifications.
-
-            if (mMediaSessionManager != null) {
-                // TODO: Should this really be for all users? It appears that inactive users
-                //  can't have active sessions, which would mean it is fine.
-                final List<MediaController> sessions =
-                        mMediaSessionManager.getActiveSessionsForUser(null, UserHandle.ALL);
-
-                for (MediaController aController : sessions) {
-                    // now to see if we have one like this
-                    final String pkg = aController.getPackageName();
-
-                    for (NotificationEntry entry : allNotifications) {
-                        if (entry.getSbn().getPackageName().equals(pkg)) {
-                            if (DEBUG_MEDIA) {
-                                Log.v(TAG, "DEBUG_MEDIA: found controller matching "
-                                        + entry.getSbn().getKey());
-                            }
-                            controller = aController;
-                            mediaNotification = entry;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
 
         if (controller != null && !sameSessions(mMediaController, controller)) {
             // We have a new media session
@@ -550,8 +514,6 @@
 
     @Override
     public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
-        pw.print("    mMediaSessionManager=");
-        pw.println(mMediaSessionManager);
         pw.print("    mMediaNotificationKey=");
         pw.println(mMediaNotificationKey);
         pw.print("    mMediaController=");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
index dd44f72..2b5453a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationRemoteInputManager.java
@@ -33,6 +33,7 @@
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.ArraySet;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.Pair;
 import android.view.MotionEvent;
@@ -53,9 +54,9 @@
 import com.android.systemui.R;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.dagger.StatusBarDependenciesModule;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -66,6 +67,7 @@
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.RemoteInputUriController;
 import com.android.systemui.statusbar.policy.RemoteInputView;
+import com.android.systemui.util.DumpUtilsKt;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -104,7 +106,7 @@
     private final Lazy<Optional<StatusBar>> mStatusBarOptionalLazy;
 
     protected final Context mContext;
-    protected final FeatureFlags mFeatureFlags;
+    protected final NotifPipelineFlags mNotifPipelineFlags;
     private final UserManager mUserManager;
     private final KeyguardManager mKeyguardManager;
     private final RemoteInputNotificationRebuilder mRebuilder;
@@ -255,7 +257,7 @@
      */
     public NotificationRemoteInputManager(
             Context context,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             NotificationLockscreenUserManager lockscreenUserManager,
             SmartReplyController smartReplyController,
             NotificationVisibilityProvider visibilityProvider,
@@ -269,7 +271,7 @@
             ActionClickLogger logger,
             DumpManager dumpManager) {
         mContext = context;
-        mFeatureFlags = featureFlags;
+        mNotifPipelineFlags = notifPipelineFlags;
         mLockscreenUserManager = lockscreenUserManager;
         mSmartReplyController = smartReplyController;
         mVisibilityProvider = visibilityProvider;
@@ -281,7 +283,7 @@
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mRebuilder = rebuilder;
-        if (!featureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
             mRemoteInputListener = createLegacyRemoteInputLifetimeExtender(mainHandler,
                     notificationEntryManager, smartReplyController);
         }
@@ -318,7 +320,7 @@
 
     /** Add a listener for various remote input events.  Works with NEW pipeline only. */
     public void setRemoteInputListener(@NonNull RemoteInputListener remoteInputListener) {
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             if (mRemoteInputListener != null) {
                 throw new IllegalStateException("mRemoteInputListener is already set");
             }
@@ -376,7 +378,7 @@
                 }
             }
         });
-        if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
             mSmartReplyController.setCallback((entry, reply) -> {
                 StatusBarNotification newSbn = mRebuilder.rebuildForSendingSmartReply(entry, reply);
                 mEntryManager.updateNotification(newSbn, null /* ranking */);
@@ -507,15 +509,19 @@
 
         riv.setRevealParameters(cx, cy, r);
         riv.setPendingIntent(pendingIntent);
+        riv.getController().setPendingIntent(pendingIntent);
         riv.setRemoteInput(inputs, input, editedSuggestionInfo);
+        riv.getController().setRemoteInput(input);
+        riv.getController().setRemoteInputs(inputs);
         riv.focusAnimated();
         if (userMessageContent != null) {
             riv.setEditTextContent(userMessageContent);
         }
         if (deferBouncer) {
             final ExpandableNotificationRow finalRow = row;
-            riv.setBouncerChecker(() -> !authBypassCheck.canSendRemoteInputWithoutBouncer()
-                    && showBouncerForRemoteInput(view, pendingIntent, finalRow));
+            riv.getController().setBouncerChecker(() ->
+                    !authBypassCheck.canSendRemoteInputWithoutBouncer()
+                            && showBouncerForRemoteInput(view, pendingIntent, finalRow));
         }
 
         return true;
@@ -649,9 +655,19 @@
     }
 
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+        IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
+        if (mRemoteInputController != null) {
+            pw.println("mRemoteInputController: " + mRemoteInputController);
+            pw.increaseIndent();
+            mRemoteInputController.dump(pw);
+            pw.decreaseIndent();
+        }
         if (mRemoteInputListener instanceof Dumpable) {
+            pw.println("mRemoteInputListener: " + mRemoteInputListener.getClass().getSimpleName());
+            pw.increaseIndent();
             ((Dumpable) mRemoteInputListener).dump(fd, pw, args);
+            pw.decreaseIndent();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index ff3e97a..00e7a03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar;
 
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
+
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Handler;
@@ -33,11 +35,14 @@
 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.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.legacy.LowPriorityInflationHelper;
 import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
 import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
+import com.android.systemui.statusbar.notification.collection.render.NotifStats;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -91,10 +96,12 @@
     private final DynamicPrivacyController mDynamicPrivacyController;
     private final KeyguardBypassController mBypassController;
     private final ForegroundServiceSectionController mFgsSectionController;
+    private final NotifPipelineFlags mNotifPipelineFlags;
     private AssistantFeedbackController mAssistantFeedbackController;
     private final Context mContext;
 
     private NotificationPresenter mPresenter;
+    private NotifStackController mStackController;
     private NotificationListContainer mListContainer;
 
     // Used to help track down re-entrant calls to our update methods, which will cause bugs.
@@ -121,7 +128,8 @@
             ForegroundServiceSectionController fgsSectionController,
             DynamicChildBindController dynamicChildBindController,
             LowPriorityInflationHelper lowPriorityInflationHelper,
-            AssistantFeedbackController assistantFeedbackController) {
+            AssistantFeedbackController assistantFeedbackController,
+            NotifPipelineFlags notifPipelineFlags) {
         mContext = context;
         mHandler = mainHandler;
         mFeatureFlags = featureFlags;
@@ -132,6 +140,7 @@
         mStatusBarStateController = (SysuiStatusBarStateController) statusBarStateController;
         mEntryManager = notificationEntryManager;
         mFgsSectionController = fgsSectionController;
+        mNotifPipelineFlags = notifPipelineFlags;
         Resources res = context.getResources();
         mAlwaysExpandNonGroupedNotification =
                 res.getBoolean(R.bool.config_alwaysExpandNonGroupedNotifications);
@@ -143,10 +152,12 @@
     }
 
     public void setUpWithPresenter(NotificationPresenter presenter,
+            NotifStackController stackController,
             NotificationListContainer listContainer) {
         mPresenter = presenter;
+        mStackController = stackController;
         mListContainer = listContainer;
-        if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
             mDynamicPrivacyController.addListener(this);
         }
     }
@@ -157,7 +168,7 @@
     //TODO: Rewrite this to focus on Entries, or some other data object instead of views
     public void updateNotificationViews() {
         Assert.isMainThread();
-        if (!mFeatureFlags.checkLegacyPipelineEnabled()) {
+        if (!mNotifPipelineFlags.checkLegacyPipelineEnabled()) {
             return;
         }
 
@@ -324,6 +335,7 @@
         mTmpChildOrderMap.clear();
 
         updateRowStatesInternal();
+        updateNotifStats();
 
         mListContainer.onNotificationViewUpdateFinished();
 
@@ -331,6 +343,56 @@
     }
 
     /**
+     * In the spirit of unidirectional data flow, calculate this information when the notification
+     * views are updated, and set it once, speeding up lookups later.
+     * This is analogous to logic in the
+     * {@link com.android.systemui.statusbar.notification.collection.coordinator.StackCoordinator}
+     */
+    private void updateNotifStats() {
+        boolean hasNonClearableAlertingNotifs = false;
+        boolean hasClearableAlertingNotifs = false;
+        boolean hasNonClearableSilentNotifs = false;
+        boolean hasClearableSilentNotifs = false;
+        final int childCount = mListContainer.getContainerChildCount();
+        int visibleTopLevelEntries = 0;
+        for (int i = 0; i < childCount; i++) {
+            View child = mListContainer.getContainerChildAt(i);
+            if (child == null || child.getVisibility() == View.GONE) {
+                continue;
+            }
+            if (!(child instanceof ExpandableNotificationRow)) {
+                continue;
+            }
+            final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            boolean isSilent = row.getEntry().getBucket() == BUCKET_SILENT;
+            // NOTE: NotificationEntry.isClearable() will internally check group children to ensure
+            //  the group itself definitively clearable.
+            boolean isClearable = row.getEntry().isClearable();
+            visibleTopLevelEntries++;
+            if (isSilent) {
+                if (isClearable) {
+                    hasClearableSilentNotifs = true;
+                } else {  // !isClearable
+                    hasNonClearableSilentNotifs = true;
+                }
+            } else {  // !isSilent
+                if (isClearable) {
+                    hasClearableAlertingNotifs = true;
+                } else {  // !isClearable
+                    hasNonClearableAlertingNotifs = true;
+                }
+            }
+        }
+        mStackController.setNotifStats(new NotifStats(
+                visibleTopLevelEntries /* numActiveNotifs */,
+                hasNonClearableAlertingNotifs /* hasNonClearableAlertingNotifs */,
+                hasClearableAlertingNotifs /* hasClearableAlertingNotifs */,
+                hasNonClearableSilentNotifs /* hasNonClearableSilentNotifs */,
+                hasClearableSilentNotifs /* hasClearableSilentNotifs */
+        ));
+    }
+
+    /**
      * Should a notification entry from the active list be suppressed and not show?
      */
     private boolean shouldSuppressActiveNotification(NotificationEntry ent) {
@@ -435,7 +497,7 @@
      */
     public void updateRowStates() {
         Assert.isMainThread();
-        if (!mFeatureFlags.checkLegacyPipelineEnabled()) {
+        if (!mNotifPipelineFlags.checkLegacyPipelineEnabled()) {
             return;
         }
 
@@ -524,7 +586,7 @@
 
     @Override
     public void onDynamicPrivacyChanged() {
-        mFeatureFlags.assertLegacyPipelineEnabled();
+        mNotifPipelineFlags.assertLegacyPipelineEnabled();
         if (mPerformingUpdate) {
             Log.w(TAG, "onDynamicPrivacyChanged made a re-entrant call");
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
index cde3b0e..31ab6bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java
@@ -23,11 +23,15 @@
 import android.os.SystemProperties;
 import android.service.notification.StatusBarNotification;
 import android.util.ArrayMap;
+import android.util.IndentingPrintWriter;
 import android.util.Pair;
 
+import androidx.annotation.NonNull;
+
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.policy.RemoteInputUriController;
 import com.android.systemui.statusbar.policy.RemoteInputView;
+import com.android.systemui.util.DumpUtilsKt;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
@@ -293,6 +297,28 @@
         mRemoteInputUriController.grantInlineReplyUriPermission(sbn, data);
     }
 
+    /** dump debug info; called by {@link NotificationRemoteInputManager} */
+    public void dump(@NonNull IndentingPrintWriter pw) {
+        pw.print("isRemoteInputActive: ");
+        pw.println(isRemoteInputActive()); // Note that this prunes the mOpen list, printed later.
+        pw.println("mOpen: " + mOpen.size());
+        DumpUtilsKt.withIncreasedIndent(pw, () -> {
+            for (Pair<WeakReference<NotificationEntry>, Object> open : mOpen) {
+                NotificationEntry entry = open.first.get();
+                pw.println(entry == null ? "???" : entry.getKey());
+            }
+        });
+        pw.println("mSpinning: " + mSpinning.size());
+        DumpUtilsKt.withIncreasedIndent(pw, () -> {
+            for (String key : mSpinning.keySet()) {
+                pw.println(key);
+            }
+        });
+        pw.println(mSpinning);
+        pw.print("mDelegate: ");
+        pw.println(mDelegate);
+    }
+
     public interface Callback {
         default void onRemoteInputActive(boolean active) {}
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/charging/WiredChargingRippleController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/WiredChargingRippleController.kt
index 04c60fc..fa99353 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/charging/WiredChargingRippleController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/WiredChargingRippleController.kt
@@ -36,6 +36,7 @@
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.util.leak.RotationUtils
 import com.android.systemui.R
+import com.android.systemui.flags.Flags
 import com.android.systemui.util.time.SystemClock
 import java.io.PrintWriter
 import javax.inject.Inject
@@ -61,7 +62,7 @@
     private val uiEventLogger: UiEventLogger
 ) {
     private var pluggedIn: Boolean? = null
-    private val rippleEnabled: Boolean = featureFlags.isChargingRippleEnabled &&
+    private val rippleEnabled: Boolean = featureFlags.isEnabled(Flags.CHARGING_RIPPLE) &&
             !SystemProperties.getBoolean("persist.debug.suppress-charging-ripple", false)
     private var normalizedPortPosX: Float = context.resources.getFloat(
             R.dimen.physical_charger_port_location_normalized_x)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
index 9ae7ea2..1d67062 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/MobileSignalController.java
@@ -55,6 +55,7 @@
 import com.android.settingslib.net.SignalStrengthUtil;
 import com.android.systemui.R;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.util.CarrierConfigTracker;
 
 import java.io.PrintWriter;
@@ -192,7 +193,8 @@
             SubscriptionDefaults defaults,
             Looper receiverLooper,
             CarrierConfigTracker carrierConfigTracker,
-            FeatureFlags featureFlags
+            FeatureFlags featureFlags,
+            StatusBarFlags statusBarFlags
     ) {
         super("MobileSignalController(" + info.getSubscriptionId() + ")", context,
                 NetworkCapabilities.TRANSPORT_CELLULAR, callbackHandler,
@@ -226,8 +228,8 @@
         mImsMmTelManager = ImsMmTelManager.createForSubscriptionId(info.getSubscriptionId());
         mMobileStatusTracker = new MobileStatusTracker(mPhone, receiverLooper,
                 info, mDefaults, mMobileCallback);
-        mProviderModelBehavior = featureFlags.isCombinedStatusBarSignalIconsEnabled();
-        mProviderModelSetting = featureFlags.isProviderModelSettingEnabled();
+        mProviderModelBehavior = featureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS);
+        mProviderModelSetting = statusBarFlags.isProviderModelSettingEnabled();
     }
 
     void setConfiguration(Config config) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index 26780eb..03d443e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -73,6 +73,7 @@
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.qs.tiles.dialog.InternetDialogFactory;
 import com.android.systemui.qs.tiles.dialog.InternetDialogUtil;
 import com.android.systemui.settings.CurrentUserTracker;
@@ -135,6 +136,7 @@
     private Config mConfig;
     private final CarrierConfigTracker mCarrierConfigTracker;
     private final FeatureFlags mFeatureFlags;
+    private final StatusBarFlags mStatusBarFlags;
     private final DumpManager mDumpManager;
 
     private TelephonyCallback.ActiveDataSubscriptionIdListener mPhoneStateListener;
@@ -210,6 +212,7 @@
                     mReceiverHandler.post(() -> handleConfigurationChanged());
                 }
             };
+
     /**
      * Construct this controller object and register for updates.
      */
@@ -233,6 +236,7 @@
             @Main Handler handler,
             InternetDialogFactory internetDialogFactory,
             FeatureFlags featureFlags,
+            StatusBarFlags statusBarFlags,
             DumpManager dumpManager) {
         this(context, connectivityManager,
                 telephonyManager,
@@ -252,6 +256,7 @@
                 demoModeController,
                 carrierConfigTracker,
                 featureFlags,
+                statusBarFlags,
                 dumpManager);
         mReceiverHandler.post(mRegisterListeners);
         mMainHandler = handler;
@@ -275,6 +280,7 @@
             DemoModeController demoModeController,
             CarrierConfigTracker carrierConfigTracker,
             FeatureFlags featureFlags,
+            StatusBarFlags statusBarFlags,
             DumpManager dumpManager
     ) {
         mContext = context;
@@ -294,6 +300,7 @@
         mDemoModeController = demoModeController;
         mCarrierConfigTracker = carrierConfigTracker;
         mFeatureFlags = featureFlags;
+        mStatusBarFlags = statusBarFlags;
         mDumpManager = dumpManager;
 
         // telephony
@@ -316,7 +323,7 @@
         });
         mWifiSignalController = new WifiSignalController(mContext, mHasMobileDataFeature,
                 mCallbackHandler, this, mWifiManager, mConnectivityManager, networkScoreManager,
-                mFeatureFlags);
+                mStatusBarFlags);
 
         mEthernetSignalController = new EthernetSignalController(mContext, mCallbackHandler, this);
 
@@ -441,8 +448,8 @@
         };
 
         mDemoModeController.addCallback(this);
-        mProviderModelBehavior = mFeatureFlags.isCombinedStatusBarSignalIconsEnabled();
-        mProviderModelSetting = mFeatureFlags.isProviderModelSettingEnabled();
+        mProviderModelBehavior = mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS);
+        mProviderModelSetting = mStatusBarFlags.isProviderModelSettingEnabled();
 
         mDumpManager.registerDumpable(TAG, this);
     }
@@ -958,7 +965,7 @@
                         mHasMobileDataFeature, mPhone.createForSubscriptionId(subId),
                         mCallbackHandler, this, subscriptions.get(i),
                         mSubDefaults, mReceiverHandler.getLooper(), mCarrierConfigTracker,
-                        mFeatureFlags);
+                        mFeatureFlags, mStatusBarFlags);
                 controller.setUserSetupComplete(mUserSetup);
                 mMobileSignalControllers.put(subId, controller);
                 if (subscriptions.get(i).getSimSlotIndex() == 0) {
@@ -1436,7 +1443,7 @@
                 mConfig, mHasMobileDataFeature,
                 mPhone.createForSubscriptionId(info.getSubscriptionId()), mCallbackHandler, this,
                 info, mSubDefaults, mReceiverHandler.getLooper(), mCarrierConfigTracker,
-                mFeatureFlags);
+                mFeatureFlags, mStatusBarFlags);
         mMobileSignalControllers.put(id, controller);
         controller.getState().userSetup = true;
         return info;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/StatusBarFlags.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/StatusBarFlags.java
new file mode 100644
index 0000000..89d4bf5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/StatusBarFlags.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 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.connectivity;
+
+import android.content.Context;
+import android.util.FeatureFlagUtils;
+
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.flags.FeatureFlags;
+
+import javax.inject.Inject;
+
+/**
+ * Class for providing StatusBar specific logic around {@link FeatureFlags}.
+ */
+@SysUISingleton
+public class StatusBarFlags {
+    private final Context mContext;
+
+    @Inject
+    public StatusBarFlags(Context context) {
+        mContext = context;
+    }
+
+    /** System setting for provider model behavior */
+    public boolean isProviderModelSettingEnabled() {
+        return FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SETTINGS_PROVIDER_MODEL);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java
index 103ca0e..f8f7b7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/WifiSignalController.java
@@ -34,7 +34,6 @@
 import com.android.settingslib.mobile.TelephonyIcons;
 import com.android.settingslib.wifi.WifiStatusTracker;
 import com.android.systemui.R;
-import com.android.systemui.flags.FeatureFlags;
 
 import java.io.PrintWriter;
 
@@ -55,7 +54,7 @@
             WifiManager wifiManager,
             ConnectivityManager connectivityManager,
             NetworkScoreManager networkScoreManager,
-            FeatureFlags featureFlags) {
+            StatusBarFlags statusBarFlags) {
         super("WifiSignalController", context, NetworkCapabilities.TRANSPORT_WIFI,
                 callbackHandler, networkController);
         mWifiManager = wifiManager;
@@ -68,7 +67,7 @@
                     new WifiTrafficStateCallback());
         }
         mCurrentState.iconGroup = mLastState.iconGroup = mUnmergedWifiIconGroup;
-        mProviderModelSetting = featureFlags.isProviderModelSettingEnabled();
+        mProviderModelSetting = statusBarFlags.isProviderModelSettingEnabled();
     }
 
     @Override
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 d5cba72..8c54de4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
@@ -52,6 +52,7 @@
 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.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -70,6 +71,7 @@
 import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
 import com.android.systemui.statusbar.phone.SystemUIHostDialogProvider;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
+import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallFlags;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger;
 import com.android.systemui.statusbar.policy.RemoteInputUriController;
 import com.android.systemui.statusbar.window.StatusBarWindowController;
@@ -98,7 +100,7 @@
     @Provides
     static NotificationRemoteInputManager provideNotificationRemoteInputManager(
             Context context,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             NotificationLockscreenUserManager lockscreenUserManager,
             SmartReplyController smartReplyController,
             NotificationVisibilityProvider visibilityProvider,
@@ -113,7 +115,7 @@
             DumpManager dumpManager) {
         return new NotificationRemoteInputManager(
                 context,
-                featureFlags,
+                notifPipelineFlags,
                 lockscreenUserManager,
                 smartReplyController,
                 visibilityProvider,
@@ -141,7 +143,7 @@
             KeyguardBypassController keyguardBypassController,
             NotifPipeline notifPipeline,
             NotifCollection notifCollection,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             @Main DelayableExecutor mainExecutor,
             MediaDataManager mediaDataManager,
             DumpManager dumpManager) {
@@ -155,7 +157,7 @@
                 keyguardBypassController,
                 notifPipeline,
                 notifCollection,
-                featureFlags,
+                notifPipelineFlags,
                 mainExecutor,
                 mediaDataManager,
                 dumpManager);
@@ -211,7 +213,8 @@
             ForegroundServiceSectionController fgsSectionController,
             DynamicChildBindController dynamicChildBindController,
             LowPriorityInflationHelper lowPriorityInflationHelper,
-            AssistantFeedbackController assistantFeedbackController) {
+            AssistantFeedbackController assistantFeedbackController,
+            NotifPipelineFlags notifPipelineFlags) {
         return new NotificationViewHierarchyManager(
                 context,
                 mainHandler,
@@ -227,7 +230,8 @@
                 fgsSectionController,
                 dynamicChildBindController,
                 lowPriorityInflationHelper,
-                assistantFeedbackController);
+                assistantFeedbackController,
+                notifPipelineFlags);
     }
 
     /**
@@ -266,7 +270,6 @@
     @SysUISingleton
     static OngoingCallController provideOngoingCallController(
             CommonNotifCollection notifCollection,
-            FeatureFlags featureFlags,
             SystemClock systemClock,
             ActivityStarter activityStarter,
             @Main Executor mainExecutor,
@@ -275,19 +278,22 @@
             DumpManager dumpManager,
             StatusBarWindowController statusBarWindowController,
             SwipeStatusBarAwayGestureHandler swipeStatusBarAwayGestureHandler,
-            StatusBarStateController statusBarStateController) {
+            StatusBarStateController statusBarStateController,
+            OngoingCallFlags ongoingCallFlags) {
+
+        boolean ongoingCallInImmersiveEnabled = ongoingCallFlags.isInImmersiveEnabled();
         Optional<StatusBarWindowController> windowController =
-                featureFlags.isOngoingCallInImmersiveEnabled()
+                ongoingCallInImmersiveEnabled
                         ? Optional.of(statusBarWindowController)
                         : Optional.empty();
         Optional<SwipeStatusBarAwayGestureHandler> gestureHandler =
-                featureFlags.isOngoingCallInImmersiveEnabled()
+                ongoingCallInImmersiveEnabled
                         ? Optional.of(swipeStatusBarAwayGestureHandler)
                         : Optional.empty();
         OngoingCallController ongoingCallController =
                 new OngoingCallController(
                         notifCollection,
-                        featureFlags,
+                        ongoingCallFlags,
                         systemClock,
                         activityStarter,
                         mainExecutor,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index 4e5bc8e..a44de2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -44,6 +44,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.util.concurrency.Execution
@@ -158,7 +159,7 @@
     fun isEnabled(): Boolean {
         execution.assertIsMainThread()
 
-        return featureFlags.isSmartspaceEnabled && plugin != null
+        return featureFlags.isEnabled(Flags.SMARTSPACE) && plugin != null
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
new file mode 100644
index 0000000..1432f78
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotifPipelineFlags.kt
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 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
+
+import android.content.Context
+import android.util.Log
+import android.widget.Toast
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import javax.inject.Inject
+
+class NotifPipelineFlags @Inject constructor(
+    val context: Context,
+    val featureFlags: FeatureFlags
+) {
+    fun checkLegacyPipelineEnabled(): Boolean {
+        if (!isNewPipelineEnabled()) {
+            return true
+        }
+        Log.d("NotifPipeline", "Old pipeline code running w/ new pipeline enabled", Exception())
+        Toast.makeText(context, "Old pipeline code running!", Toast.LENGTH_SHORT).show()
+        return false
+    }
+
+    fun assertLegacyPipelineEnabled(): Unit =
+        check(!isNewPipelineEnabled()) { "Old pipeline code running w/ new pipeline enabled" }
+
+    fun isNewPipelineEnabled(): Boolean =
+        featureFlags.isEnabled(Flags.NEW_NOTIFICATION_PIPELINE_RENDERING)
+
+    fun isDevLoggingEnabled(): Boolean =
+        featureFlags.isEnabled(Flags.NOTIFICATION_PIPELINE_DEVELOPER_LOGGING)
+
+    fun isSmartspaceDedupingEnabled(): Boolean =
+            featureFlags.isEnabled(Flags.SMARTSPACE) &&
+                    featureFlags.isEnabled(Flags.SMARTSPACE_DEDUPING)
+}
\ No newline at end of file
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 2437415..0389a7b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -38,7 +38,6 @@
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.Dumpable;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationListener.NotificationHandler;
@@ -102,7 +101,7 @@
 
     private final NotificationEntryManagerLogger mLogger;
     private final NotificationGroupManagerLegacy mGroupManager;
-    private final FeatureFlags mFeatureFlags;
+    private final NotifPipelineFlags mNotifPipelineFlags;
     private final Lazy<NotificationRowBinder> mNotificationRowBinderLazy;
     private final Lazy<NotificationRemoteInputManager> mRemoteInputManagerLazy;
     private final LeakDetector mLeakDetector;
@@ -149,7 +148,7 @@
     public NotificationEntryManager(
             NotificationEntryManagerLogger logger,
             NotificationGroupManagerLegacy groupManager,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             Lazy<NotificationRowBinder> notificationRowBinderLazy,
             Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
             LeakDetector leakDetector,
@@ -159,7 +158,7 @@
     ) {
         mLogger = logger;
         mGroupManager = groupManager;
-        mFeatureFlags = featureFlags;
+        mNotifPipelineFlags = notifPipelineFlags;
         mNotificationRowBinderLazy = notificationRowBinderLazy;
         mRemoteInputManagerLazy = notificationRemoteInputManagerLazy;
         mLeakDetector = leakDetector;
@@ -637,7 +636,7 @@
         }
 
         // Construct the expanded view.
-        if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
             mNotificationRowBinderLazy.get().inflateViews(entry, null, mInflationCallback);
         }
 
@@ -694,7 +693,7 @@
             listener.onEntryUpdated(entry, fromSystem);
         }
 
-        if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
             mNotificationRowBinderLazy.get().inflateViews(entry, null, mInflationCallback);
         }
 
@@ -721,12 +720,12 @@
      * @param reason why the notifications are updating
      */
     public void updateNotifications(String reason) {
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             mLogger.logUseWhileNewPipelineActive("updateNotifications", reason);
             return;
         }
         reapplyFilterAndSort(reason);
-        if (mPresenter != null) {
+        if (mPresenter != null && !mNotifPipelineFlags.isNewPipelineEnabled()) {
             mPresenter.updateNotificationViews(reason);
         }
     }
@@ -792,6 +791,7 @@
      * these don't exist, although there are a couple exceptions.
      */
     public Iterable<NotificationEntry> getPendingNotificationsIterator() {
+        mNotifPipelineFlags.checkLegacyPipelineEnabled();
         return mPendingNotifications.values();
     }
 
@@ -804,6 +804,7 @@
      * @return a {@link NotificationEntry} if it has been prepared, else null
      */
     public NotificationEntry getActiveNotificationUnfiltered(String key) {
+        mNotifPipelineFlags.checkLegacyPipelineEnabled();
         return mActiveNotifications.get(key);
     }
 
@@ -812,6 +813,7 @@
      * notification doesn't exist.
      */
     public NotificationEntry getPendingOrActiveNotif(String key) {
+        mNotifPipelineFlags.checkLegacyPipelineEnabled();
         NotificationEntry entry = mPendingNotifications.get(key);
         if (entry != null) {
             return entry;
@@ -884,7 +886,7 @@
 
     /** Resorts / filters the current notification set with the current RankingMap */
     public void reapplyFilterAndSort(String reason) {
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             mLogger.logUseWhileNewPipelineActive("reapplyFilterAndSort", reason);
             return;
         }
@@ -893,7 +895,7 @@
 
     /** Calls to NotificationRankingManager and updates mSortedAndFiltered */
     private void updateRankingAndSort(@NonNull RankingMap rankingMap, String reason) {
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             mLogger.logUseWhileNewPipelineActive("updateRankingAndSort", reason);
             return;
         }
@@ -946,6 +948,7 @@
      * @return A read-only list of the currently active notifications
      */
     public List<NotificationEntry> getVisibleNotifications() {
+        mNotifPipelineFlags.checkLegacyPipelineEnabled();
         return mReadOnlyNotifications;
     }
 
@@ -955,17 +958,20 @@
      */
     @Override
     public Collection<NotificationEntry> getAllNotifs() {
+        mNotifPipelineFlags.checkLegacyPipelineEnabled();
         return mReadOnlyAllNotifications;
     }
 
     @Nullable
     @Override
     public NotificationEntry getEntry(String key) {
+        mNotifPipelineFlags.checkLegacyPipelineEnabled();
         return getPendingOrActiveNotif(key);
     }
 
     /** @return A count of the active notifications */
     public int getActiveNotificationsCount() {
+        mNotifPipelineFlags.checkLegacyPipelineEnabled();
         return mReadOnlyNotifications.size();
     }
 
@@ -973,6 +979,7 @@
      * @return {@code true} if there is at least one notification that should be visible right now
      */
     public boolean hasActiveNotifications() {
+        mNotifPipelineFlags.checkLegacyPipelineEnabled();
         return mReadOnlyNotifications.size() != 0;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFadeAware.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFadeAware.java
new file mode 100644
index 0000000..8d2e3c9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFadeAware.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 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;
+
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+/**
+ * Used to let views that have an alpha not apply the HARDWARE layer type directly, and instead
+ * delegate that to specific children.  This is useful if we want to fake not having overlapping
+ * rendering to avoid layer trashing, when fading out a view that is also changing.
+ */
+public interface NotificationFadeAware {
+    /**
+     * Calls {@link View#setLayerType} with {@link View#LAYER_TYPE_HARDWARE} if faded and
+     * {@link View#LAYER_TYPE_NONE} otherwise.
+     */
+    static void setLayerTypeForFaded(@Nullable View view, boolean faded) {
+        if (view != null) {
+            int newLayerType = faded ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE;
+            view.setLayerType(newLayerType, null);
+        }
+    }
+
+    /**
+     * Used like {@link View#setLayerType} with {@link View#LAYER_TYPE_HARDWARE} or
+     * {@link View#LAYER_TYPE_NONE} except that instead of necessarily affecting this view
+     * specifically, this may delegate the call to child views.
+     *
+     * When set to <code>true</code>, the view has two possible paths:
+     *  1. If a hardware layer is required to ensure correct appearance of this view, then
+     *    set that layer type.
+     *  2. Otherwise, delegate this call to children, who might make that call for themselves.
+     *
+     * When set to <code>false</code>, the view should undo the above, typically by calling
+     *  {@link View#setLayerType} with {@link View#LAYER_TYPE_NONE} on itself and children, and
+     *  delegating to this method on children where implemented.
+     *
+     * When this delegates to {@link View#setLayerType} on this view or a subview, `null` will be
+     * passed for the `paint` argument of that call.
+     */
+    void setNotificationFaded(boolean faded);
+
+    /**
+     * Interface for the top level notification view that fades and optimizes that through deep
+     * awareness of individual components.
+     */
+    interface FadeOptimizedNotification extends NotificationFadeAware {
+        /** Top-level feature switch */
+        boolean FADE_LAYER_OPTIMIZATION_ENABLED = true;
+
+        /** Determine if the notification is currently faded. */
+        boolean isNotificationFaded();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionClassifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionClassifier.kt
new file mode 100644
index 0000000..1f2d0fe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/SectionClassifier.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
+import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
+import javax.inject.Inject
+
+/**
+ * A class which is used to classify the sections.
+ * NOTE: This class exists to avoid putting metadata like "isMinimized" on the NotifSection
+ */
+@SysUISingleton
+class SectionClassifier @Inject constructor() {
+    private lateinit var lowPrioritySections: Set<NotifSectioner>
+
+    /**
+     * Feed the provider the information it needs about which sections should have minimized top
+     * level views, so that it can calculate the correct minimized state.
+     */
+    fun setMinimizedSections(sections: Collection<NotifSectioner>) {
+        lowPrioritySections = sections.toSet()
+    }
+
+    /**
+     * Determine if the given section is minimized
+     */
+    fun isMinimizedSection(section: NotifSection): Boolean {
+        return lowPrioritySections.contains(section.sectioner)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
index 0ea6857..918843c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java
@@ -19,8 +19,6 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 
-import com.android.systemui.statusbar.notification.collection.coordinator.PreparationCoordinator;
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -61,24 +59,6 @@
         mSummary = summary;
     }
 
-    /**
-     * @see #getUntruncatedChildCount()
-     */
-    public void setUntruncatedChildCount(int childCount) {
-        mUntruncatedChildCount = childCount;
-    }
-
-    /**
-     * Get the untruncated number of children from the data model, including those that will not
-     * have views bound. This includes children that {@link PreparationCoordinator} will filter out
-     * entirely when they are beyond the last visible child.
-     *
-     * TODO: This should move to some shared class between the model and view hierarchy
-     */
-    public int getUntruncatedChildCount() {
-        return mUntruncatedChildCount;
-    }
-
     void clearChildren() {
         mChildren.clear();
     }
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 52c5c3e..6be8a49 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
@@ -55,15 +55,26 @@
                     interactionTracker.hasUserInteractedWith(entry.getKey()));
             if (entry instanceof GroupEntry) {
                 GroupEntry ge = (GroupEntry) entry;
+                NotificationEntry summary = ge.getSummary();
+                if (summary != null) {
+                    dumpEntry(summary,
+                            topEntryIndex + ":*",
+                            childEntryIndent,
+                            sb,
+                            true,
+                            includeRecordKeeping,
+                            interactionTracker.hasUserInteractedWith(summary.getKey()));
+                }
                 List<NotificationEntry> children = ge.getChildren();
                 for (int childIndex = 0;  childIndex < children.size(); childIndex++) {
-                    dumpEntry(children.get(childIndex),
+                    NotificationEntry child = children.get(childIndex);
+                    dumpEntry(child,
                             topEntryIndex + "." + childIndex,
                             childEntryIndent,
                             sb,
                             true,
                             includeRecordKeeping,
-                            interactionTracker.hasUserInteractedWith(entry.getKey()));
+                            interactionTracker.hasUserInteractedWith(child.getKey()));
                 }
             }
         }
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 f36f430..f8f1279 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
@@ -66,7 +66,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.dump.LogBufferEulogizer;
-import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent;
 import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
 import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer.BatchableNotificationHandler;
@@ -132,7 +132,7 @@
 public class NotifCollection implements Dumpable {
     private final IStatusBarService mStatusBarService;
     private final SystemClock mClock;
-    private final FeatureFlags mFeatureFlags;
+    private final NotifPipelineFlags mNotifPipelineFlags;
     private final NotifCollectionLogger mLogger;
     private final Handler mMainHandler;
     private final LogBufferEulogizer mEulogizer;
@@ -156,7 +156,7 @@
     public NotifCollection(
             IStatusBarService statusBarService,
             SystemClock clock,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             NotifCollectionLogger logger,
             @Main Handler mainHandler,
             LogBufferEulogizer logBufferEulogizer,
@@ -164,7 +164,7 @@
         Assert.isMainThread();
         mStatusBarService = statusBarService;
         mClock = clock;
-        mFeatureFlags = featureFlags;
+        mNotifPipelineFlags = notifPipelineFlags;
         mLogger = logger;
         mMainHandler = mainHandler;
         mEulogizer = logBufferEulogizer;
@@ -245,9 +245,15 @@
             DismissedByUserStats stats = entriesToDismiss.get(i).second;
 
             requireNonNull(stats);
-            if (entry != mNotificationSet.get(entry.getKey())) {
+            NotificationEntry storedEntry = mNotificationSet.get(entry.getKey());
+            if (storedEntry == null) {
+                mLogger.logNonExistentNotifDismissed(entry.getKey());
+                continue;
+            }
+            if (entry != storedEntry) {
                 throw mEulogizer.record(
-                        new IllegalStateException("Invalid entry: " + entry.getKey()));
+                        new IllegalStateException("Invalid entry: "
+                                + "different stored and dismissed entries for " + entry.getKey()));
             }
 
             if (entry.getDismissState() == DISMISSED) {
@@ -395,7 +401,7 @@
         final NotificationEntry entry = mNotificationSet.get(sbn.getKey());
         if (entry == null) {
             // TODO (b/160008901): Throw an exception here
-            mLogger.logNoNotificationToRemoveWithKey(sbn.getKey());
+            mLogger.logNoNotificationToRemoveWithKey(sbn.getKey(), reason);
             return;
         }
 
@@ -489,6 +495,37 @@
         }
     }
 
+    /**
+     * Get the group summary entry
+     * @param group
+     * @return
+     */
+    @Nullable
+    public NotificationEntry getGroupSummary(String group) {
+        return mNotificationSet
+                .values()
+                .stream()
+                .filter(it -> Objects.equals(it.getSbn().getGroup(), group))
+                .filter(it -> it.getSbn().getNotification().isGroupSummary())
+                .findFirst().orElse(null);
+    }
+
+    /**
+     * Checks if the entry is the only child in the logical group
+     * @param entry
+     * @return
+     */
+    public boolean isOnlyChildInGroup(NotificationEntry entry) {
+        String group = entry.getSbn().getGroup();
+        return mNotificationSet.get(entry.getKey()) == entry
+                && mNotificationSet
+                .values()
+                .stream()
+                .filter(it -> Objects.equals(it.getSbn().getGroup(), group))
+                .filter(it -> !it.getSbn().getNotification().isGroupSummary())
+                .count() == 1;
+    }
+
     private void applyRanking(@NonNull RankingMap rankingMap) {
         for (NotificationEntry entry : mNotificationSet.values()) {
             if (!isCanceled(entry)) {
@@ -503,7 +540,7 @@
                     // TODO: (b/145659174) update the sbn's overrideGroupKey in
                     //  NotificationEntry.setRanking instead of here once we fully migrate to the
                     //  NewNotifPipeline
-                    if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+                    if (mNotifPipelineFlags.isNewPipelineEnabled()) {
                         final String newOverrideGroupKey = ranking.getOverrideGroupKey();
                         if (!Objects.equals(entry.getSbn().getOverrideGroupKey(),
                                 newOverrideGroupKey)) {
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 4f3c287..4daed77 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
@@ -93,7 +93,7 @@
             public void onAsyncInflationFinished(NotificationEntry entry) {
                 mNotifErrorManager.clearInflationError(entry);
                 if (callback != null) {
-                    callback.onInflationFinished(entry);
+                    callback.onInflationFinished(entry, entry.getRowController());
                 }
             }
         };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt
index 9ae9fe5..6fbed9a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.kt
@@ -16,6 +16,9 @@
 package com.android.systemui.statusbar.notification.collection
 
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderGroupListener
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
 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
@@ -31,6 +34,7 @@
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
+import com.android.systemui.statusbar.notification.collection.render.RenderStageManager
 import javax.inject.Inject
 
 /**
@@ -65,11 +69,15 @@
  *  9. Finalize filters are fired on each notification ([.addFinalizeFilter])
  *  10. OnBeforeRenderListListeners are fired ([.addOnBeforeRenderListListener])
  *  11. The list is handed off to the view layer to be rendered
+ *  12. OnAfterRenderListListeners are fired ([.addOnAfterRenderListListener])
+ *  13. OnAfterRenderGroupListeners are fired ([.addOnAfterRenderGroupListener])
+ *  13. OnAfterRenderEntryListeners are fired ([.addOnAfterRenderEntryListener])
  */
 @SysUISingleton
 class NotifPipeline @Inject constructor(
     private val mNotifCollection: NotifCollection,
-    private val mShadeListBuilder: ShadeListBuilder
+    private val mShadeListBuilder: ShadeListBuilder,
+    private val mRenderStageManager: RenderStageManager
 ) : CommonNotifCollection {
     /**
      * Returns the list of all known notifications, i.e. the notifications that are currently posted
@@ -206,6 +214,28 @@
     }
 
     /**
+     * Called at the end of the pipeline after the notif list has been handed off to the view layer.
+     */
+    fun addOnAfterRenderListListener(listener: OnAfterRenderListListener) {
+        mRenderStageManager.addOnAfterRenderListListener(listener)
+    }
+
+    /**
+     * Called at the end of the pipeline after a group has been handed off to the view layer.
+     */
+    fun addOnAfterRenderGroupListener(listener: OnAfterRenderGroupListener) {
+        mRenderStageManager.addOnAfterRenderGroupListener(listener)
+    }
+
+    /**
+     * Called at the end of the pipeline after an entry has been handed off to the view layer.
+     * This will be called for every top level entry, every group summary, and every group child.
+     */
+    fun addOnAfterRenderEntryListener(listener: OnAfterRenderEntryListener) {
+        mRenderStageManager.addOnAfterRenderEntryListener(listener)
+    }
+
+    /**
      * Get an object which can be used to update a notification (internally to the pipeline)
      * in response to a user action.
      *
@@ -218,8 +248,8 @@
 
     /**
      * Returns a read-only view in to the current shade list, i.e. the list of notifications that
-     * are currently present in the shade. If this method is called during pipeline execution it
-     * will return the current state of the list, which will likely be only partially-generated.
+     * are currently present in the shade.
+     * @throws IllegalStateException if called during pipeline execution.
      */
     val shadeList: List<ListEntry>
         get() = mShadeListBuilder.shadeList
@@ -227,21 +257,20 @@
     /**
      * Constructs a flattened representation of the notification tree, where each group will have
      * the summary (if present) followed by the children.
+     * @throws IllegalStateException if called during pipeline execution.
      */
     fun getFlatShadeList(): List<NotificationEntry> = shadeList.flatMap { entry ->
         when (entry) {
             is NotificationEntry -> sequenceOf(entry)
-            is GroupEntry -> (entry.summary?.let { sequenceOf(it) }.orEmpty() +
-                    entry.children)
+            is GroupEntry -> sequenceOf(entry.summary).filterNotNull() + entry.children
             else -> throw RuntimeException("Unexpected entry $entry")
         }
     }
 
     /**
      * Returns the number of notifications currently shown in the shade. This includes all
-     * children and summary notifications. If this method is called during pipeline execution it
-     * will return the number of notifications in its current state, which will likely be only
-     * partially-generated.
+     * children and summary notifications.
+     * @throws IllegalStateException if called during pipeline execution.
      */
     fun getShadeListCount(): Int = shadeList.sumOf { entry ->
         // include the summary in the count
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 72cd951..748c69d 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
@@ -42,6 +42,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.statusbar.NotificationInteractionTracker;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener;
@@ -87,6 +88,7 @@
     private final NotificationInteractionTracker mInteractionTracker;
     // used exclusivly by ShadeListBuilder#notifySectionEntriesUpdated
     private final ArrayList<ListEntry> mTempSectionMembers = new ArrayList<>();
+    private final boolean mAlwaysLogList;
 
     private List<ListEntry> mNotifList = new ArrayList<>();
     private List<ListEntry> mNewNotifList = new ArrayList<>();
@@ -119,6 +121,7 @@
     @Inject
     public ShadeListBuilder(
             SystemClock systemClock,
+            NotifPipelineFlags flags,
             ShadeListBuilderLogger logger,
             DumpManager dumpManager,
             NotificationInteractionTracker interactionTracker
@@ -126,6 +129,7 @@
         Assert.isMainThread();
         mSystemClock = systemClock;
         mLogger = logger;
+        mAlwaysLogList = flags.isDevLoggingEnabled();
         mInteractionTracker = interactionTracker;
         dumpManager.registerDumpable(TAG, this);
 
@@ -253,6 +257,9 @@
 
     List<ListEntry> getShadeList() {
         Assert.isMainThread();
+        // NOTE: Accessing this method when the pipeline is running is generally going to provide
+        //  incorrect results, and indicates a poorly behaved component of the pipeline.
+        mPipelineState.requireState(STATE_IDLE);
         return mReadOnlyNotifList;
     }
 
@@ -404,7 +411,7 @@
                 mIterationCount,
                 mReadOnlyNotifList.size(),
                 countChildren(mReadOnlyNotifList));
-        if (mIterationCount % 10 == 0) {
+        if (mAlwaysLogList || mIterationCount % 10 == 0) {
             mLogger.logFinalList(mNotifList);
         }
         mPipelineState.setState(STATE_IDLE);
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 d013261..e9b7caa5 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
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.collection.coordinator;
 
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -57,6 +58,7 @@
 public class BubbleCoordinator implements Coordinator {
     private static final String TAG = "BubbleCoordinator";
 
+    private final NotifPipelineFlags mNotifPipelineFlags;
     private final Optional<BubblesManager> mBubblesManagerOptional;
     private final Optional<Bubbles> mBubblesOptional;
     private final NotifCollection mNotifCollection;
@@ -66,9 +68,11 @@
 
     @Inject
     public BubbleCoordinator(
+            NotifPipelineFlags notifPipelineFlags,
             Optional<BubblesManager> bubblesManagerOptional,
             Optional<Bubbles> bubblesOptional,
             NotifCollection notifCollection) {
+        mNotifPipelineFlags = notifPipelineFlags;
         mBubblesManagerOptional = bubblesManagerOptional;
         mBubblesOptional = bubblesOptional;
         mNotifCollection = notifCollection;
@@ -130,6 +134,14 @@
                 DismissedByUserStats dismissedByUserStats,
                 int reason
         ) {
+            if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
+                // The `entry` will be from whichever pipeline is active, so if the old pipeline is
+                // running, make sure that we use the new pipeline's entry (if it still exists).
+                NotificationEntry newPipelineEntry = mNotifPipeline.getEntry(entry.getKey());
+                if (newPipelineEntry != null) {
+                    entry = newPipelineEntry;
+                }
+            }
             if (isInterceptingDismissal(entry)) {
                 mInterceptedDismissalEntries.remove(entry.getKey());
                 mOnEndDismissInterception.onEndDismissInterception(mDismissInterceptor, entry,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java
index 992d898..bd011c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinator.java
@@ -19,6 +19,7 @@
 import androidx.annotation.NonNull;
 
 import com.android.systemui.communal.CommunalStateController;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -26,6 +27,8 @@
 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 
+import java.util.concurrent.Executor;
+
 import javax.inject.Inject;
 
 /**
@@ -34,14 +37,17 @@
  */
 @CoordinatorScope
 public class CommunalCoordinator implements Coordinator {
+    final Executor mExecutor;
     final CommunalStateController mCommunalStateController;
     final NotificationEntryManager mNotificationEntryManager;
     final NotificationLockscreenUserManager mNotificationLockscreenUserManager;
 
     @Inject
-    public CommunalCoordinator(NotificationEntryManager notificationEntryManager,
+    public CommunalCoordinator(@Main Executor executor,
+            NotificationEntryManager notificationEntryManager,
             NotificationLockscreenUserManager notificationLockscreenUserManager,
             CommunalStateController communalStateController) {
+        mExecutor = executor;
         mNotificationEntryManager = notificationEntryManager;
         mNotificationLockscreenUserManager = notificationLockscreenUserManager;
         mCommunalStateController = communalStateController;
@@ -57,8 +63,10 @@
     final CommunalStateController.Callback mStateCallback = new CommunalStateController.Callback() {
         @Override
         public void onCommunalViewShowingChanged() {
-            mFilter.invalidateList();
-            mNotificationEntryManager.updateNotifications("Communal mode state changed");
+            mExecutor.execute(() -> {
+                mFilter.invalidateList();
+                mNotificationEntryManager.updateNotifications("Communal mode state changed");
+            });
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt
new file mode 100644
index 0000000..82b1268
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinator.kt
@@ -0,0 +1,35 @@
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import android.util.ArrayMap
+import com.android.systemui.statusbar.notification.collection.GroupEntry
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
+import com.android.systemui.statusbar.notification.collection.render.NotifGroupController
+import javax.inject.Inject
+
+/** A small coordinator which calculates, stores, and applies the untruncated child count. */
+@CoordinatorScope
+class GroupCountCoordinator @Inject constructor() : Coordinator {
+    private val untruncatedChildCounts = ArrayMap<GroupEntry, Int>()
+
+    override fun attach(pipeline: NotifPipeline) {
+        pipeline.addOnBeforeFinalizeFilterListener(::onBeforeFinalizeFilter)
+        pipeline.addOnAfterRenderGroupListener(::onAfterRenderGroup)
+    }
+
+    private fun onBeforeFinalizeFilter(entries: List<ListEntry>) {
+        // save untruncated child counts to our internal map
+        untruncatedChildCounts.clear()
+        entries.asSequence().filterIsInstance<GroupEntry>().forEach { groupEntry ->
+            untruncatedChildCounts[groupEntry] = groupEntry.children.size
+        }
+    }
+
+    private fun onAfterRenderGroup(group: GroupEntry, controller: NotifGroupController) {
+        // find the untruncated child count for a group and apply it to the controller
+        val count = untruncatedChildCounts[group]
+        checkNotNull(count) { "No untruncated child count for group: ${group.key}" }
+        controller.setUntruncatedChildCount(count)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
index 7cbda25d..a16b565 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.kt
@@ -17,13 +17,12 @@
 
 import com.android.systemui.Dumpable
 import com.android.systemui.dump.DumpManager
-import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.statusbar.notification.NotifPipelineFlags
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
 import java.io.FileDescriptor
 import java.io.PrintWriter
-import java.util.ArrayList
 import javax.inject.Inject
 
 /**
@@ -35,7 +34,7 @@
 @CoordinatorScope
 class NotifCoordinatorsImpl @Inject constructor(
     dumpManager: DumpManager,
-    featureFlags: FeatureFlags,
+    notifPipelineFlags: NotifPipelineFlags,
     hideLocallyDismissedNotifsCoordinator: HideLocallyDismissedNotifsCoordinator,
     hideNotifsForOtherUsersCoordinator: HideNotifsForOtherUsersCoordinator,
     keyguardCoordinator: KeyguardCoordinator,
@@ -47,8 +46,11 @@
     gutsCoordinator: GutsCoordinator,
     conversationCoordinator: ConversationCoordinator,
     preparationCoordinator: PreparationCoordinator,
+    groupCountCoordinator: GroupCountCoordinator,
     mediaCoordinator: MediaCoordinator,
     remoteInputCoordinator: RemoteInputCoordinator,
+    rowAppearanceCoordinator: RowAppearanceCoordinator,
+    stackCoordinator: StackCoordinator,
     shadeEventCoordinator: ShadeEventCoordinator,
     smartspaceDedupingCoordinator: SmartspaceDedupingCoordinator,
     viewConfigCoordinator: ViewConfigCoordinator,
@@ -73,25 +75,28 @@
         mCoordinators.add(deviceProvisionedCoordinator)
         mCoordinators.add(bubbleCoordinator)
         mCoordinators.add(conversationCoordinator)
+        mCoordinators.add(groupCountCoordinator)
         mCoordinators.add(mediaCoordinator)
         mCoordinators.add(remoteInputCoordinator)
+        mCoordinators.add(rowAppearanceCoordinator)
+        mCoordinators.add(stackCoordinator)
         mCoordinators.add(shadeEventCoordinator)
         mCoordinators.add(viewConfigCoordinator)
         mCoordinators.add(visualStabilityCoordinator)
         mCoordinators.add(communalCoordinator)
         mCoordinators.add(sensitiveContentCoordinator)
-        if (featureFlags.isSmartspaceDedupingEnabled) {
+        if (notifPipelineFlags.isSmartspaceDedupingEnabled()) {
             mCoordinators.add(smartspaceDedupingCoordinator)
         }
-        if (featureFlags.isNewNotifPipelineRenderingEnabled) {
+        if (notifPipelineFlags.isNewPipelineEnabled()) {
             mCoordinators.add(headsUpCoordinator)
             mCoordinators.add(gutsCoordinator)
             mCoordinators.add(preparationCoordinator)
         }
 
         // Manually add Ordered Sections
-        // HeadsUp > FGS > People > Alerting > Silent > Unknown/Default
-        if (featureFlags.isNewNotifPipelineRenderingEnabled) {
+        // HeadsUp > FGS > People > Alerting > Silent > Minimized > Unknown/Default
+        if (notifPipelineFlags.isNewPipelineEnabled()) {
             mOrderedSections.add(headsUpCoordinator.sectioner) // HeadsUp
         }
         mOrderedSections.add(appOpsCoordinator.sectioner) // ForegroundService
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 644f248..bbb97d1 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
@@ -31,19 +31,19 @@
 
 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;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope;
 import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
 import com.android.systemui.statusbar.notification.collection.inflation.NotifUiAdjustment;
 import com.android.systemui.statusbar.notification.collection.inflation.NotifUiAdjustmentProvider;
-import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
 import com.android.systemui.statusbar.notification.collection.render.NotifViewBarn;
+import com.android.systemui.statusbar.notification.collection.render.NotifViewController;
 import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager;
 import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager.NotifInflationErrorListener;
 
@@ -61,8 +61,7 @@
  * If a notification was uninflated, this coordinator will filter the notification out from the
  * {@link ShadeListBuilder} until it is inflated.
  */
-// TODO(b/204468557): Move to @CoordinatorScope
-@SysUISingleton
+@CoordinatorScope
 public class PreparationCoordinator implements Coordinator {
     private static final String TAG = "PreparationCoordinator";
 
@@ -145,7 +144,7 @@
 
         pipeline.addCollectionListener(mNotifCollectionListener);
         // Inflate after grouping/sorting since that affects what views to inflate.
-        pipeline.addOnBeforeFinalizeFilterListener(mOnBeforeFinalizeFilterListener);
+        pipeline.addOnBeforeFinalizeFilterListener(this::inflateAllRequiredViews);
         pipeline.addFinalizeFilter(mNotifInflationErrorFilter);
         pipeline.addFinalizeFilter(mNotifInflatingFilter);
     }
@@ -182,9 +181,6 @@
         }
     };
 
-    private final OnBeforeFinalizeFilterListener mOnBeforeFinalizeFilterListener =
-            entries -> inflateAllRequiredViews(entries);
-
     private final NotifFilter mNotifInflationErrorFilter = new NotifFilter(
             TAG + "InflationError") {
         /**
@@ -256,7 +252,6 @@
             ListEntry entry = entries.get(i);
             if (entry instanceof GroupEntry) {
                 GroupEntry groupEntry = (GroupEntry) entry;
-                groupEntry.setUntruncatedChildCount(groupEntry.getChildren().size());
                 inflateRequiredGroupViews(groupEntry);
             } else {
                 NotificationEntry notifEntry = (NotificationEntry) entry;
@@ -363,17 +358,17 @@
         mInflatingNotifs.remove(entry);
     }
 
-    private void onInflationFinished(NotificationEntry entry) {
+    private void onInflationFinished(NotificationEntry entry, NotifViewController controller) {
         mLogger.logNotifInflated(entry.getKey());
         mInflatingNotifs.remove(entry);
-        mViewBarn.registerViewForEntry(entry, entry.getRowController());
+        mViewBarn.registerViewForEntry(entry, controller);
         mInflationStates.put(entry, STATE_INFLATED);
         mNotifInflatingFilter.invalidateList();
     }
 
     private void freeNotifViews(NotificationEntry entry) {
         mViewBarn.removeViewForEntry(entry);
-        entry.setRow(null);
+        // TODO: clear the entry's row here, or even better, stop setting the row on the entry!
         mInflationStates.put(entry, STATE_UNINFLATED);
     }
 
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 c60ebcd..57fd197 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
@@ -20,11 +20,11 @@
 import android.annotation.Nullable;
 
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.SectionClassifier;
 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.coordinator.dagger.CoordinatorScope;
-import com.android.systemui.statusbar.notification.collection.inflation.NotifUiAdjustmentProvider;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
@@ -51,7 +51,7 @@
     public static final boolean SHOW_ALL_SECTIONS = false;
     private final StatusBarStateController mStatusBarStateController;
     private final HighPriorityProvider mHighPriorityProvider;
-    private final NotifUiAdjustmentProvider mAdjustmentProvider;
+    private final SectionClassifier mSectionClassifier;
     private final NodeController mSilentNodeController;
     private final SectionHeaderController mSilentHeaderController;
     private final NodeController mAlertingHeaderController;
@@ -62,13 +62,13 @@
     public RankingCoordinator(
             StatusBarStateController statusBarStateController,
             HighPriorityProvider highPriorityProvider,
-            NotifUiAdjustmentProvider adjustmentProvider,
+            SectionClassifier sectionClassifier,
             @AlertingHeader NodeController alertingHeaderController,
             @SilentHeader SectionHeaderController silentHeaderController,
             @SilentHeader NodeController silentNodeController) {
         mStatusBarStateController = statusBarStateController;
         mHighPriorityProvider = highPriorityProvider;
-        mAdjustmentProvider = adjustmentProvider;
+        mSectionClassifier = sectionClassifier;
         mAlertingHeaderController = alertingHeaderController;
         mSilentNodeController = silentNodeController;
         mSilentHeaderController = silentHeaderController;
@@ -77,7 +77,7 @@
     @Override
     public void attach(NotifPipeline pipeline) {
         mStatusBarStateController.addCallback(mStatusBarStateCallback);
-        mAdjustmentProvider.setLowPrioritySections(Collections.singleton(mMinimizedNotifSectioner));
+        mSectionClassifier.setMinimizedSections(Collections.singleton(mMinimizedNotifSectioner));
 
         pipeline.addPreGroupFilter(mSuspendedFilter);
         pipeline.addPreGroupFilter(mDndVisualEffectsFilter);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt
index 3397815..2608c30 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RemoteInputCoordinator.kt
@@ -22,7 +22,6 @@
 import android.util.Log
 import androidx.annotation.VisibleForTesting
 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.NotificationRemoteInputManager
@@ -32,6 +31,7 @@
 import com.android.systemui.statusbar.SmartReplyController
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
 import com.android.systemui.statusbar.notification.collection.notifcollection.SelfTrackingLifetimeExtender
 import com.android.systemui.statusbar.notification.collection.notifcollection.InternalNotifUpdater
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
@@ -61,7 +61,7 @@
 /** Whether this class should print spammy debug logs */
 private val DEBUG: Boolean by lazy { Log.isLoggable(TAG, Log.DEBUG) }
 
-@SysUISingleton
+@CoordinatorScope
 class RemoteInputCoordinator @Inject constructor(
     dumpManager: DumpManager,
     private val mRebuilder: RemoteInputNotificationRebuilder,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt
new file mode 100644
index 0000000..c8f7360
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinator.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2021 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 android.content.Context
+import com.android.systemui.R
+import com.android.systemui.statusbar.notification.AssistantFeedbackController
+import com.android.systemui.statusbar.notification.SectionClassifier
+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.coordinator.dagger.CoordinatorScope
+import com.android.systemui.statusbar.notification.collection.render.NotifRowController
+import javax.inject.Inject
+
+/**
+ * A small coordinator which updates the notif rows with data related to the current shade after
+ * they are fully attached.
+ */
+@CoordinatorScope
+class RowAppearanceCoordinator @Inject internal constructor(
+    context: Context,
+    private var mAssistantFeedbackController: AssistantFeedbackController,
+    private var mSectionClassifier: SectionClassifier
+) : Coordinator {
+
+    private var entryToExpand: NotificationEntry? = null
+
+    /**
+     * `true` if notifications not part of a group should by default be rendered in their
+     * expanded state. If `false`, then only the first notification will be expanded if
+     * possible.
+     */
+    private val mAlwaysExpandNonGroupedNotification =
+        context.resources.getBoolean(R.bool.config_alwaysExpandNonGroupedNotifications)
+
+    override fun attach(pipeline: NotifPipeline) {
+        pipeline.addOnBeforeRenderListListener(::onBeforeRenderList)
+        pipeline.addOnAfterRenderEntryListener(::onAfterRenderEntry)
+    }
+
+    private fun onBeforeRenderList(list: List<ListEntry>) {
+        entryToExpand = list.firstOrNull()?.representativeEntry?.takeIf { entry ->
+            !mSectionClassifier.isMinimizedSection(entry.section!!)
+        }
+    }
+
+    private fun onAfterRenderEntry(entry: NotificationEntry, controller: NotifRowController) {
+        // If mAlwaysExpandNonGroupedNotification is false, then only expand the
+        // very first notification and if it's not a child of grouped notifications.
+        controller.setSystemExpanded(mAlwaysExpandNonGroupedNotification || entry == entryToExpand)
+        // Show/hide the feedback icon
+        controller.showFeedbackIcon(
+            mAssistantFeedbackController.showFeedbackIndicator(entry),
+            mAssistantFeedbackController.getFeedbackResources(entry)
+        )
+        // Show the "alerted" bell icon
+        controller.setLastAudiblyAlertedMs(entry.lastAudiblyAlertedMs)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
new file mode 100644
index 0000000..38f11fc
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinator.kt
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 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 com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
+import com.android.systemui.statusbar.notification.collection.render.NotifStats
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController
+import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
+import com.android.systemui.statusbar.phone.NotificationIconAreaController
+import javax.inject.Inject
+
+/**
+ * A small coordinator which updates the notif stack (the view layer which holds notifications)
+ * with high-level data after the stack is populated with the final entries.
+ */
+@CoordinatorScope
+class StackCoordinator @Inject internal constructor(
+    private val notificationIconAreaController: NotificationIconAreaController
+) : Coordinator {
+
+    override fun attach(pipeline: NotifPipeline) {
+        pipeline.addOnAfterRenderListListener(::onAfterRenderList)
+    }
+
+    fun onAfterRenderList(entries: List<ListEntry>, controller: NotifStackController) {
+        controller.setNotifStats(calculateNotifStats(entries))
+        notificationIconAreaController.updateNotificationIcons(entries)
+    }
+
+    private fun calculateNotifStats(entries: List<ListEntry>): NotifStats {
+        var hasNonClearableAlertingNotifs = false
+        var hasClearableAlertingNotifs = false
+        var hasNonClearableSilentNotifs = false
+        var hasClearableSilentNotifs = false
+        entries.forEach {
+            val isSilent = it.section!!.bucket == BUCKET_SILENT
+            // NOTE: NotificationEntry.isClearable will internally check group children to ensure
+            //  the group itself definitively clearable.
+            val isClearable = it.representativeEntry!!.isClearable
+            when {
+                isSilent && isClearable -> hasClearableSilentNotifs = true
+                isSilent && !isClearable -> hasNonClearableSilentNotifs = true
+                !isSilent && isClearable -> hasClearableAlertingNotifs = true
+                !isSilent && !isClearable -> hasNonClearableAlertingNotifs = true
+            }
+        }
+        val stats = NotifStats(
+            numActiveNotifs = entries.size,
+            hasNonClearableAlertingNotifs = hasNonClearableAlertingNotifs,
+            hasClearableAlertingNotifs = hasClearableAlertingNotifs,
+            hasNonClearableSilentNotifs = hasNonClearableSilentNotifs,
+            hasClearableSilentNotifs = hasClearableSilentNotifs
+        )
+        return stats
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
index 5b86de2..832df4d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
@@ -19,9 +19,9 @@
 import com.android.internal.widget.MessagingGroup
 import com.android.internal.widget.MessagingMessage
 import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener
 import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl
+import com.android.systemui.statusbar.notification.NotifPipelineFlags
 import com.android.systemui.statusbar.notification.collection.NotifPipeline
 import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager
@@ -37,7 +37,7 @@
 class ViewConfigCoordinator @Inject internal constructor(
     configurationController: ConfigurationController,
     lockscreenUserManager: NotificationLockscreenUserManagerImpl,
-    featureFlags: FeatureFlags,
+    notifPipelineFlags: NotifPipelineFlags,
     private val mGutsManager: NotificationGutsManager,
     private val mKeyguardUpdateMonitor: KeyguardUpdateMonitor
 ) : Coordinator, UserChangedListener, ConfigurationController.ConfigurationListener {
@@ -47,7 +47,7 @@
     private var mPipeline: NotifPipeline? = null
 
     init {
-        if (featureFlags.isNewNotifPipelineRenderingEnabled) {
+        if (notifPipelineFlags.isNewPipelineEnabled()) {
             lockscreenUserManager.addUserChangedListener(this)
             configurationController.addCallback(this)
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
index c59f184..d98e7f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.collection.inflation
 
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.render.NotifViewController
 
 /**
  * Used by the [PreparationCoordinator].  When notifications are added or updated, the
@@ -49,7 +50,7 @@
      * Callback once all the views are inflated and bound for a given NotificationEntry.
      */
     interface InflationCallback {
-        fun onInflationFinished(entry: NotificationEntry)
+        fun onInflationFinished(entry: NotificationEntry, controller: NotifViewController)
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
index 3290cdf..497691d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
@@ -17,9 +17,9 @@
 package com.android.systemui.statusbar.notification.collection.inflation
 
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.SectionClassifier
 import com.android.systemui.statusbar.notification.collection.GroupEntry
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
-import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
 import javax.inject.Inject
 
 /**
@@ -27,25 +27,17 @@
  * to ensure that notifications are reinflated when ranking-derived information changes.
  */
 @SysUISingleton
-open class NotifUiAdjustmentProvider @Inject constructor() {
-
-    private lateinit var lowPrioritySections: Set<NotifSectioner>
-
-    /**
-     * Feed the provider the information it needs about which sections should have minimized top
-     * level views, so that it can calculate the correct minimized value in the adjustment.
-     */
-    fun setLowPrioritySections(sections: Collection<NotifSectioner>) {
-        lowPrioritySections = sections.toSet()
-    }
+open class NotifUiAdjustmentProvider @Inject constructor(
+    private val sectionClassifier: SectionClassifier
+) {
 
     private fun isEntryMinimized(entry: NotificationEntry): Boolean {
         val section = entry.section ?: error("Entry must have a section to determine if minimized")
         val parent = entry.parent ?: error("Entry must have a parent to determine if minimized")
-        val isLowPrioritySection = lowPrioritySections.contains(section.sectioner)
+        val isMinimizedSection = sectionClassifier.isMinimizedSection(section)
         val isTopLevelEntry = parent == GroupEntry.ROOT_ENTRY
         val isGroupSummary = parent.summary == entry
-        return isLowPrioritySection && (isTopLevelEntry || isGroupSummary)
+        return isMinimizedSection && (isTopLevelEntry || isGroupSummary)
     }
 
     /**
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 5c8e8b2..4c7b2bb 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
@@ -25,12 +25,12 @@
 
 import com.android.internal.util.NotificationMessagingUtil;
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationUiAdjustment;
 import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationClicker;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.legacy.LowPriorityInflationHelper;
@@ -55,7 +55,6 @@
     private static final String TAG = "NotificationViewManager";
 
     private final Context mContext;
-    private final FeatureFlags mFeatureFlags;
     private final NotificationMessagingUtil mMessagingUtil;
     private final NotificationRemoteInputManager mNotificationRemoteInputManager;
     private final NotificationLockscreenUserManager mNotificationLockscreenUserManager;
@@ -66,6 +65,7 @@
             mExpandableNotificationRowComponentBuilder;
     private final IconManager mIconManager;
     private final LowPriorityInflationHelper mLowPriorityInflationHelper;
+    private final NotifPipelineFlags mNotifPipelineFlags;
 
     private NotificationPresenter mPresenter;
     private NotificationListContainer mListContainer;
@@ -75,7 +75,6 @@
     @Inject
     public NotificationRowBinderImpl(
             Context context,
-            FeatureFlags featureFlags,
             NotificationMessagingUtil notificationMessagingUtil,
             NotificationRemoteInputManager notificationRemoteInputManager,
             NotificationLockscreenUserManager notificationLockscreenUserManager,
@@ -84,9 +83,9 @@
             Provider<RowInflaterTask> rowInflaterTaskProvider,
             ExpandableNotificationRowComponent.Builder expandableNotificationRowComponentBuilder,
             IconManager iconManager,
-            LowPriorityInflationHelper lowPriorityInflationHelper) {
+            LowPriorityInflationHelper lowPriorityInflationHelper,
+            NotifPipelineFlags notifPipelineFlags) {
         mContext = context;
-        mFeatureFlags = featureFlags;
         mNotifBindPipeline = notifBindPipeline;
         mRowContentBindStage = rowContentBindStage;
         mMessagingUtil = notificationMessagingUtil;
@@ -96,6 +95,7 @@
         mExpandableNotificationRowComponentBuilder = expandableNotificationRowComponentBuilder;
         mIconManager = iconManager;
         mLowPriorityInflationHelper = lowPriorityInflationHelper;
+        mNotifPipelineFlags = notifPipelineFlags;
     }
 
     /**
@@ -126,7 +126,7 @@
             throws InflationException {
         if (params == null) {
             // weak assert that the params should always be passed in the new pipeline
-            mFeatureFlags.checkLegacyPipelineEnabled();
+            mNotifPipelineFlags.checkLegacyPipelineEnabled();
         }
         ViewGroup parent = mListContainer.getViewParentForNotification(entry);
 
@@ -187,7 +187,7 @@
             NotificationUiAdjustment oldAdjustment,
             NotificationUiAdjustment newAdjustment,
             NotificationRowContentBinder.InflationCallback callback) {
-        mFeatureFlags.checkLegacyPipelineEnabled();
+        mNotifPipelineFlags.checkLegacyPipelineEnabled();
         if (NotificationUiAdjustment.needReinflate(oldAdjustment, newAdjustment)) {
             if (entry.rowExists()) {
                 ExpandableNotificationRow row = entry.getRow();
@@ -238,7 +238,7 @@
             isLowPriority = inflaterParams.isLowPriority();
         } else {
             // LEGACY pipeline
-            mFeatureFlags.checkLegacyPipelineEnabled();
+            mNotifPipelineFlags.checkLegacyPipelineEnabled();
             // If this is our first time inflating, we don't actually know the groupings for real
             // yet, so we might actually inflate a low priority content view incorrectly here and
             // have to correct it later in the pipeline. On subsequent inflations (i.e. updates),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java
index 66ec30d..f50038c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/OnUserInteractionCallbackImpl.java
@@ -108,11 +108,10 @@
     @Override
     @Nullable
     public NotificationEntry getGroupSummaryToDismiss(NotificationEntry entry) {
-        if (entry.getParent() != null
-                && entry.getParent().getSummary() != null
-                && mGroupMembershipManager.isOnlyChildInGroup(entry)) {
-            NotificationEntry groupSummary = entry.getParent().getSummary();
-            return groupSummary.isClearable() ? groupSummary : null;
+        String group = entry.getSbn().getGroup();
+        if (mNotifCollection.isOnlyChildInGroup(entry)) {
+            NotificationEntry summary = mNotifCollection.getGroupSummary(group);
+            if (summary != null && summary.isClearable()) return summary;
         }
         return null;
     }
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 a98531f..f9358eb 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
@@ -21,8 +21,8 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.NotificationListener;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -30,6 +30,8 @@
 import com.android.systemui.statusbar.notification.collection.coalescer.GroupCoalescer;
 import com.android.systemui.statusbar.notification.collection.coordinator.NotifCoordinators;
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
+import com.android.systemui.statusbar.notification.collection.render.RenderStageManager;
 import com.android.systemui.statusbar.notification.collection.render.ShadeViewManagerFactory;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 
@@ -47,11 +49,12 @@
     private final GroupCoalescer mGroupCoalescer;
     private final NotifCollection mNotifCollection;
     private final ShadeListBuilder mListBuilder;
+    private final RenderStageManager mRenderStageManager;
     private final NotifCoordinators mNotifPluggableCoordinators;
     private final NotifInflaterImpl mNotifInflater;
     private final DumpManager mDumpManager;
     private final ShadeViewManagerFactory mShadeViewManagerFactory;
-    private final FeatureFlags mFeatureFlags;
+    private final NotifPipelineFlags mNotifPipelineFlags;
 
 
     @Inject
@@ -60,32 +63,36 @@
             GroupCoalescer groupCoalescer,
             NotifCollection notifCollection,
             ShadeListBuilder listBuilder,
+            RenderStageManager renderStageManager,
             NotifCoordinators notifCoordinators,
             NotifInflaterImpl notifInflater,
             DumpManager dumpManager,
             ShadeViewManagerFactory shadeViewManagerFactory,
-            FeatureFlags featureFlags) {
+            NotifPipelineFlags notifPipelineFlags
+    ) {
         mPipelineWrapper = pipelineWrapper;
         mGroupCoalescer = groupCoalescer;
         mNotifCollection = notifCollection;
         mListBuilder = listBuilder;
+        mRenderStageManager = renderStageManager;
         mNotifPluggableCoordinators = notifCoordinators;
         mDumpManager = dumpManager;
         mNotifInflater = notifInflater;
         mShadeViewManagerFactory = shadeViewManagerFactory;
-        mFeatureFlags = featureFlags;
+        mNotifPipelineFlags = notifPipelineFlags;
     }
 
     /** Hooks the new pipeline up to NotificationManager */
     public void initialize(
             NotificationListener notificationService,
             NotificationRowBinderImpl rowBinder,
-            NotificationListContainer listContainer) {
+            NotificationListContainer listContainer,
+            NotifStackController stackController) {
 
         mDumpManager.registerDumpable("NotifPipeline", this);
 
         // Setup inflation
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             mNotifInflater.setRowBinder(rowBinder);
         }
 
@@ -93,15 +100,18 @@
         mNotifPluggableCoordinators.attach(mPipelineWrapper);
 
         // Wire up pipeline
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
-            mShadeViewManagerFactory.create(listContainer).attach(mListBuilder);
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
+            mShadeViewManagerFactory
+                    .create(listContainer, stackController)
+                    .attach(mRenderStageManager);
         }
+        mRenderStageManager.attach(mListBuilder);
         mListBuilder.attach(mNotifCollection);
         mNotifCollection.attach(mGroupCoalescer);
         mGroupCoalescer.attach(notificationService);
 
         Log.d(TAG, "Notif pipeline initialized."
-                + " rendering=" + mFeatureFlags.isNewNotifPipelineRenderingEnabled());
+                + " rendering=" + mNotifPipelineFlags.isNewPipelineEnabled());
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LowPriorityInflationHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LowPriorityInflationHelper.java
index dd1f948..ae4f2bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LowPriorityInflationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LowPriorityInflationHelper.java
@@ -17,7 +17,7 @@
 package com.android.systemui.statusbar.notification.collection.legacy;
 
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.RowContentBindParams;
@@ -31,18 +31,18 @@
  */
 @SysUISingleton
 public class LowPriorityInflationHelper {
-    private final FeatureFlags mFeatureFlags;
     private final NotificationGroupManagerLegacy mGroupManager;
     private final RowContentBindStage mRowContentBindStage;
+    private final NotifPipelineFlags mNotifPipelineFlags;
 
     @Inject
     LowPriorityInflationHelper(
-            FeatureFlags featureFlags,
             NotificationGroupManagerLegacy groupManager,
-            RowContentBindStage rowContentBindStage) {
-        mFeatureFlags = featureFlags;
+            RowContentBindStage rowContentBindStage,
+            NotifPipelineFlags notifPipelineFlags) {
         mGroupManager = groupManager;
         mRowContentBindStage = rowContentBindStage;
+        mNotifPipelineFlags = notifPipelineFlags;
     }
 
     /**
@@ -59,7 +59,7 @@
     public void recheckLowPriorityViewAndInflate(
             NotificationEntry entry,
             ExpandableNotificationRow row) {
-        mFeatureFlags.checkLegacyPipelineEnabled();
+        mNotifPipelineFlags.checkLegacyPipelineEnabled();
         RowContentBindParams params = mRowContentBindStage.getStageParams(entry);
         final boolean shouldBeLowPriority = shouldUseLowPriorityView(entry);
         if (!row.isRemoved() && row.isLowPriority() != shouldBeLowPriority) {
@@ -73,7 +73,7 @@
      * Whether the notification should inflate a low priority version of its content views.
      */
     public boolean shouldUseLowPriorityView(NotificationEntry entry) {
-        mFeatureFlags.checkLegacyPipelineEnabled();
+        mNotifPipelineFlags.checkLegacyPipelineEnabled();
         return entry.isAmbient() && !mGroupManager.isChildInGroup(entry);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderEntryListener.java
new file mode 100644
index 0000000..20cd6dd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderEntryListener.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.listbuilder;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.NotifRowController;
+
+/** See {@link NotifPipeline#addOnAfterRenderEntryListener(OnAfterRenderEntryListener)} */
+public interface OnAfterRenderEntryListener {
+    /**
+     * Called at the end of the pipeline after an entry has been handed off to the view layer.
+     * This will be called for every top level entry, every group summary, and every group child.
+     *
+     * @param entry the entry to read from.
+     * @param controller the object to which data can be pushed.
+     */
+    void onAfterRenderEntry(
+            @NonNull NotificationEntry entry,
+            @NonNull NotifRowController controller);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderGroupListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderGroupListener.java
new file mode 100644
index 0000000..b1a4b65
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderGroupListener.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.listbuilder;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.statusbar.notification.collection.GroupEntry;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.render.NotifGroupController;
+
+/** See {@link NotifPipeline#addOnAfterRenderGroupListener(OnAfterRenderGroupListener)} */
+public interface OnAfterRenderGroupListener {
+    /**
+     * Called at the end of the pipeline after a group has been handed off to the view layer.
+     *
+     * @param groupEntry the entry for the group itself.
+     * @param controller the object to which data can be pushed.
+     */
+    void onAfterRenderGroup(
+            @NonNull GroupEntry groupEntry,
+            @NonNull NotifGroupController controller);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java
new file mode 100644
index 0000000..b5a0f7a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnAfterRenderListListener.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.listbuilder;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.statusbar.notification.collection.ListEntry;
+import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
+
+import java.util.List;
+
+/** See {@link NotifPipeline#addOnAfterRenderListListener(OnAfterRenderListListener)} */
+public interface OnAfterRenderListListener {
+    /**
+     * Called at the end of the pipeline after the notif list has been handed off to the view layer.
+     *
+     * @param entries The current list of top-level entries. Note that this is a live view into the
+     * current list and will change whenever the pipeline is rerun.
+     * @param controller An object for setting state on the shade.
+     */
+    void onAfterRenderList(
+            @NonNull List<ListEntry> entries,
+            @NonNull NotifStackController controller);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
index 1ebc66e..7302de5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifCollectionLogger.kt
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.collection.notifcollection
 
 import android.os.RemoteException
+import android.service.notification.NotificationListenerService
 import android.service.notification.NotificationListenerService.RankingMap
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.LogLevel.DEBUG
@@ -25,9 +26,36 @@
 import com.android.systemui.log.LogLevel.WARNING
 import com.android.systemui.log.LogLevel.WTF
 import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.statusbar.notification.collection.NotifCollection
+import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import javax.inject.Inject
 
+fun cancellationReasonDebugString(@CancellationReason reason: Int) =
+    "$reason:" + when (reason) {
+        -1 -> "REASON_NOT_CANCELED" // NotifCollection.REASON_NOT_CANCELED
+        NotifCollection.REASON_UNKNOWN -> "REASON_UNKNOWN"
+        NotificationListenerService.REASON_CLICK -> "REASON_CLICK"
+        NotificationListenerService.REASON_CANCEL_ALL -> "REASON_CANCEL_ALL"
+        NotificationListenerService.REASON_ERROR -> "REASON_ERROR"
+        NotificationListenerService.REASON_PACKAGE_CHANGED -> "REASON_PACKAGE_CHANGED"
+        NotificationListenerService.REASON_USER_STOPPED -> "REASON_USER_STOPPED"
+        NotificationListenerService.REASON_PACKAGE_BANNED -> "REASON_PACKAGE_BANNED"
+        NotificationListenerService.REASON_APP_CANCEL -> "REASON_APP_CANCEL"
+        NotificationListenerService.REASON_APP_CANCEL_ALL -> "REASON_APP_CANCEL_ALL"
+        NotificationListenerService.REASON_LISTENER_CANCEL -> "REASON_LISTENER_CANCEL"
+        NotificationListenerService.REASON_LISTENER_CANCEL_ALL -> "REASON_LISTENER_CANCEL_ALL"
+        NotificationListenerService.REASON_GROUP_SUMMARY_CANCELED -> "REASON_GROUP_SUMMARY_CANCELED"
+        NotificationListenerService.REASON_GROUP_OPTIMIZATION -> "REASON_GROUP_OPTIMIZATION"
+        NotificationListenerService.REASON_PACKAGE_SUSPENDED -> "REASON_PACKAGE_SUSPENDED"
+        NotificationListenerService.REASON_PROFILE_TURNED_OFF -> "REASON_PROFILE_TURNED_OFF"
+        NotificationListenerService.REASON_UNAUTOBUNDLED -> "REASON_UNAUTOBUNDLED"
+        NotificationListenerService.REASON_CHANNEL_BANNED -> "REASON_CHANNEL_BANNED"
+        NotificationListenerService.REASON_SNOOZED -> "REASON_SNOOZED"
+        NotificationListenerService.REASON_TIMEOUT -> "REASON_TIMEOUT"
+        else -> "unknown"
+    }
+
 class NotifCollectionLogger @Inject constructor(
     @NotificationLog private val buffer: LogBuffer
 ) {
@@ -56,12 +84,12 @@
         })
     }
 
-    fun logNotifRemoved(key: String, reason: Int) {
+    fun logNotifRemoved(key: String, @CancellationReason reason: Int) {
         buffer.log(TAG, INFO, {
             str1 = key
             int1 = reason
         }, {
-            "REMOVED $str1 reason=$int1"
+            "REMOVED $str1 reason=${cancellationReasonDebugString(int1)}"
         })
     }
 
@@ -81,6 +109,14 @@
         })
     }
 
+    fun logNonExistentNotifDismissed(key: String) {
+        buffer.log(TAG, INFO, {
+            str1 = key
+        }, {
+            "DISMISSED Non Existent $str1"
+        })
+    }
+
     fun logChildDismissed(entry: NotificationEntry) {
         buffer.log(TAG, DEBUG, {
             str1 = entry.key
@@ -141,11 +177,12 @@
         })
     }
 
-    fun logNoNotificationToRemoveWithKey(key: String) {
+    fun logNoNotificationToRemoveWithKey(key: String, @CancellationReason reason: Int) {
         buffer.log(TAG, ERROR, {
             str1 = key
+            int1 = reason
         }, {
-            "No notification to remove with key $str1"
+            "No notification to remove with key $str1 reason=${cancellationReasonDebugString(int1)}"
         })
     }
 
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 0478658..e7ef2ec 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
@@ -99,7 +99,7 @@
 
     private boolean hasHighPriorityCharacteristics(NotificationEntry entry) {
         return !hasUserSetImportance(entry)
-                && (entry.getSbn().getNotification().hasMediaSession()
+                && (entry.getSbn().getNotification().isMediaNotification()
                 || isPeopleNotification(entry)
                 || isMessagingStyle(entry));
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
index b9aa26f..86d263a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/GroupExpansionManagerImpl.java
@@ -25,6 +25,7 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -91,7 +92,7 @@
 
     @Override
     public void collapseGroups() {
-        for (NotificationEntry entry : mExpandedGroups) {
+        for (NotificationEntry entry : new ArrayList<>(mExpandedGroups)) {
             setGroupExpanded(entry, false);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
index 010b6f80..f59e4ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilder.kt
@@ -51,8 +51,10 @@
 
             // If this notif begins a new section, first add the section's header view
             if (section != currentSection) {
-                section.headerController?.let { headerController ->
-                    root.children.add(NodeSpecImpl(root, headerController))
+                if (section.headerController != currentSection?.headerController) {
+                    section.headerController?.let { headerController ->
+                        root.children.add(NodeSpecImpl(root, headerController))
+                    }
                 }
                 prevSections.add(currentSection)
                 currentSection = section
@@ -62,12 +64,13 @@
             root.children.add(buildNotifNode(root, entry))
         }
 
-        return root
+        return@traceSection root
     }
 
     private fun buildNotifNode(parent: NodeSpec, entry: ListEntry): NodeSpec = when (entry) {
-        is NotificationEntry -> NodeSpecImpl(parent, viewBarn.requireView(entry))
-        is GroupEntry -> NodeSpecImpl(parent, viewBarn.requireView(checkNotNull(entry.summary)))
+        is NotificationEntry -> NodeSpecImpl(parent, viewBarn.requireNodeController(entry))
+        is GroupEntry ->
+            NodeSpecImpl(parent, viewBarn.requireNodeController(checkNotNull(entry.summary)))
                 .apply { entry.children.forEach { children.add(buildNotifNode(this, it)) } }
         else -> throw RuntimeException("Unexpected entry: $entry")
     }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGroupController.kt
similarity index 66%
copy from packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
copy to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGroupController.kt
index bacc66b..e2edc01 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGroupController.kt
@@ -14,8 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.flags
+package com.android.systemui.statusbar.notification.collection.render
 
-interface FlagWriter {
-    fun setEnabled(key: Int, value: Boolean) {}
+/** A view controller for a notification group row */
+interface NotifGroupController {
+    /** Set the number of children that this group would have if not for the 8-child max */
+    fun setUntruncatedChildCount(untruncatedChildCount: Int)
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt
new file mode 100644
index 0000000..c10e401
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifRowController.kt
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2021 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.render
+
+import android.util.Pair
+
+/** A view controller for a notification row */
+interface NotifRowController {
+    /**
+     * This tells the row what the 'default expanded' state should be.  Once a user expands or
+     * contracts a row, that will set the user expanded state, which takes precedence, but
+     * collapsing the shade and re-opening it will clear the user expanded state.  This allows for
+     * nice auto expansion of the next notification as users dismiss the top notification.
+     */
+    fun setSystemExpanded(systemExpanded: Boolean)
+
+    /**
+     * Sets the timestamp that the notification was last audibly alerted, which the row uses to
+     * show a bell icon in the header which indicates to the user which notification made a noise.
+     */
+    fun setLastAudiblyAlertedMs(lastAudiblyAlertedMs: Long)
+
+    /**
+     * Sets both whether to show a feedback indicator and which resources to use for the drawable
+     * and content description.
+     */
+    fun showFeedbackIcon(showFeedbackIndicator: Boolean, feedbackResources: Pair<Int, Int>?)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt
new file mode 100644
index 0000000..b6278d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifStackController.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 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.render
+
+/** An interface by which the pipeline can make updates to the notification root view. */
+interface NotifStackController {
+    /** Provides stats about the list of notifications attached to the shade */
+    fun setNotifStats(stats: NotifStats)
+}
+
+/** Data provided to the NotificationRootController whenever the pipeline runs */
+data class NotifStats(
+    val numActiveNotifs: Int,
+    val hasNonClearableAlertingNotifs: Boolean,
+    val hasClearableAlertingNotifs: Boolean,
+    val hasNonClearableSilentNotifs: Boolean,
+    val hasClearableSilentNotifs: Boolean
+) {
+    companion object {
+        @JvmStatic
+        val empty = NotifStats(0, false, false, false, false)
+    }
+}
+
+/**
+ * An implementation of NotifStackController which provides default, no-op implementations of each
+ * method.  This is used by ArcSystemUI so that that implementation can opt-in to overriding
+ * methods, rather than forcing us to add no-op implementations in their implementation every time
+ * a method is added.
+ */
+open class DefaultNotifStackController : NotifStackController {
+    override fun setNotifStats(stats: NotifStats) {}
+}
\ No newline at end of file
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 c79f59b..fd91d5a 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
@@ -19,6 +19,7 @@
 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.collection.NotificationEntry
 import javax.inject.Inject
 
 /**
@@ -26,30 +27,39 @@
  */
 @SysUISingleton
 class NotifViewBarn @Inject constructor() {
-    private val rowMap = mutableMapOf<String, NodeController>()
+    private val rowMap = mutableMapOf<String, NotifViewController>()
 
-    fun requireView(forEntry: ListEntry): NodeController {
+    fun requireNodeController(entry: ListEntry): NodeController {
         if (DEBUG) {
-            Log.d(TAG, "requireView: $forEntry.key")
+            Log.d(TAG, "requireNodeController: ${entry.key}")
         }
-        val li = rowMap[forEntry.key]
-        if (li == null) {
-            throw IllegalStateException("No view has been registered for entry: $forEntry")
-        }
-
-        return li
+        return rowMap[entry.key] ?: error("No view has been registered for entry: ${entry.key}")
     }
 
-    fun registerViewForEntry(entry: ListEntry, controller: NodeController) {
+    fun requireGroupController(entry: NotificationEntry): NotifGroupController {
         if (DEBUG) {
-            Log.d(TAG, "registerViewForEntry: $entry.key")
+            Log.d(TAG, "requireGroupController: ${entry.key}")
+        }
+        return rowMap[entry.key] ?: error("No view has been registered for entry: ${entry.key}")
+    }
+
+    fun requireRowController(entry: NotificationEntry): NotifRowController {
+        if (DEBUG) {
+            Log.d(TAG, "requireRowController: ${entry.key}")
+        }
+        return rowMap[entry.key] ?: error("No view has been registered for entry: ${entry.key}")
+    }
+
+    fun registerViewForEntry(entry: ListEntry, controller: NotifViewController) {
+        if (DEBUG) {
+            Log.d(TAG, "registerViewForEntry: ${entry.key}")
         }
         rowMap[entry.key] = controller
     }
 
     fun removeViewForEntry(entry: ListEntry) {
         if (DEBUG) {
-            Log.d(TAG, "removeViewForEntry: $entry.key")
+            Log.d(TAG, "removeViewForEntry: ${entry.key}")
         }
         rowMap.remove(entry.key)
     }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewController.kt
similarity index 79%
copy from packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
copy to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewController.kt
index bacc66b..11d4e83 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewController.kt
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.flags
+package com.android.systemui.statusbar.notification.collection.render
 
-interface FlagWriter {
-    fun setEnabled(key: Int, value: Boolean) {}
-}
\ No newline at end of file
+interface NotifViewController : NotifGroupController, NotifRowController, NodeController
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt
new file mode 100644
index 0000000..1ea574b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifViewRenderer.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2021 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.render
+
+import com.android.systemui.statusbar.notification.collection.GroupEntry
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+
+/**
+ * This interface and the interfaces it returns define the main API surface that must be
+ * implemented by the view implementation.  The term "render" is used to indicate a handoff
+ * to the view system, whether that be to attach views to the hierarchy or to update independent
+ * view models, data stores, or adapters.
+ */
+interface NotifViewRenderer {
+
+    /**
+     * Hand off the list of notifications to the view implementation.  This may attach views to the
+     * hierarchy or simply update an independent datastore, but once called, the implementer myst
+     * also ensure that future calls to [getStackController], [getGroupController], and
+     * [getRowController] will provide valid results.
+     */
+    fun onRenderList(notifList: List<ListEntry>)
+
+    /**
+     * Provides an interface for the pipeline to update the overall shade.
+     * This will be called at most once for each time [onRenderList] is called.
+     */
+    fun getStackController(): NotifStackController
+
+    /**
+     * Provides an interface for the pipeline to update individual groups.
+     * This will be called at most once for each group in the most recent call to [onRenderList].
+     */
+    fun getGroupController(group: GroupEntry): NotifGroupController
+
+    /**
+     * Provides an interface for the pipeline to update individual entries.
+     * This will be called at most once for each entry in the most recent call to [onRenderList].
+     * This includes top level entries, group summaries, and group children.
+     */
+    fun getRowController(entry: NotificationEntry): NotifRowController
+
+    /**
+     * Invoked after the render stage manager has finished dispatching to all of the listeners.
+     *
+     * This is an opportunity for the view system to do any cleanup or trigger any finalization
+     * logic now that all data from the pipeline is known to have been set for this execution.
+     *
+     * When this is called, the view system can expect that no more calls will be made to the
+     * getters on this interface until after the next call to [onRenderList].  Additionally, there
+     * should be no further calls made on the objects previously returned by those getters.
+     */
+    fun onDispatchComplete() {}
+}
\ No newline at end of file
diff --git a/core/java/android/window/TaskFragmentAppearedInfo.aidl b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderExtensions.kt
similarity index 63%
copy from core/java/android/window/TaskFragmentAppearedInfo.aidl
copy to packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderExtensions.kt
index 3729c09..6e7f415 100644
--- a/core/java/android/window/TaskFragmentAppearedInfo.aidl
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderExtensions.kt
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
-package android.window;
+package com.android.systemui.statusbar.notification.collection.render
+
+import com.android.systemui.statusbar.notification.collection.GroupEntry
 
 /**
- * Data object for the TaskFragment info provided when a TaskFragment is presented to an organizer.
- * @hide
+ * Extension used during the render stage which assumes the summary exists, and throws a more
+ * helpful error if not.
  */
-parcelable TaskFragmentAppearedInfo;
+inline val GroupEntry.requireSummary get() = checkNotNull(summary) { "No Summary: $this" }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
new file mode 100644
index 0000000..a9c3987
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManager.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2021 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.render
+
+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
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderGroupListener
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
+import com.android.systemui.util.traceSection
+import javax.inject.Inject
+
+/**
+ * The class which is part of the pipeline which guarantees a consistent that coordinators get a
+ * consistent interface to the view system regardless of the [NotifViewRenderer] implementation
+ * provided to [setViewRenderer].
+ */
+@SysUISingleton
+class RenderStageManager @Inject constructor() {
+    private val onAfterRenderListListeners = mutableListOf<OnAfterRenderListListener>()
+    private val onAfterRenderGroupListeners = mutableListOf<OnAfterRenderGroupListener>()
+    private val onAfterRenderEntryListeners = mutableListOf<OnAfterRenderEntryListener>()
+    private var viewRenderer: NotifViewRenderer? = null
+
+    /** Attach this stage to the rest of the pipeline */
+    fun attach(listBuilder: ShadeListBuilder) {
+        listBuilder.setOnRenderListListener(::onRenderList)
+    }
+
+    private fun onRenderList(notifList: List<ListEntry>) {
+        traceSection("RenderStageManager.onRenderList") {
+            val viewRenderer = viewRenderer ?: return
+            viewRenderer.onRenderList(notifList)
+            dispatchOnAfterRenderList(viewRenderer, notifList)
+            dispatchOnAfterRenderGroups(viewRenderer, notifList)
+            dispatchOnAfterRenderEntries(viewRenderer, notifList)
+            viewRenderer.onDispatchComplete()
+        }
+    }
+
+    /** Provides this class with the view rendering implementation. */
+    fun setViewRenderer(renderer: NotifViewRenderer) {
+        viewRenderer = renderer
+    }
+
+    /** Adds a listener that will get a single callback after rendering the list. */
+    fun addOnAfterRenderListListener(listener: OnAfterRenderListListener) {
+        onAfterRenderListListeners.add(listener)
+    }
+
+    /** Adds a listener that will get a callback for each group rendered. */
+    fun addOnAfterRenderGroupListener(listener: OnAfterRenderGroupListener) {
+        onAfterRenderGroupListeners.add(listener)
+    }
+
+    /** Adds a listener that will get a callback for each entry rendered. */
+    fun addOnAfterRenderEntryListener(listener: OnAfterRenderEntryListener) {
+        onAfterRenderEntryListeners.add(listener)
+    }
+
+    private fun dispatchOnAfterRenderList(
+        viewRenderer: NotifViewRenderer,
+        entries: List<ListEntry>
+    ) {
+        traceSection("RenderStageManager.dispatchOnAfterRenderList") {
+            val stackController = viewRenderer.getStackController()
+            onAfterRenderListListeners.forEach { listener ->
+                listener.onAfterRenderList(entries, stackController)
+            }
+        }
+    }
+
+    private fun dispatchOnAfterRenderGroups(
+        viewRenderer: NotifViewRenderer,
+        entries: List<ListEntry>
+    ) {
+        traceSection("RenderStageManager.dispatchOnAfterRenderGroups") {
+            if (onAfterRenderGroupListeners.isEmpty()) {
+                return
+            }
+            entries.asSequence().filterIsInstance<GroupEntry>().forEach { group ->
+                val controller = viewRenderer.getGroupController(group)
+                onAfterRenderGroupListeners.forEach { listener ->
+                    listener.onAfterRenderGroup(group, controller)
+                }
+            }
+        }
+    }
+
+    private fun dispatchOnAfterRenderEntries(
+        viewRenderer: NotifViewRenderer,
+        entries: List<ListEntry>
+    ) {
+        traceSection("RenderStageManager.dispatchOnAfterRenderEntries") {
+            if (onAfterRenderEntryListeners.isEmpty()) {
+                return
+            }
+            entries.forEachNotificationEntry { entry ->
+                val controller = viewRenderer.getRowController(entry)
+                onAfterRenderEntryListeners.forEach { listener ->
+                    listener.onAfterRenderEntry(entry, controller)
+                }
+            }
+        }
+    }
+
+    /**
+     * Performs a forward, depth-first traversal of the list where the group's summary
+     * immediately precedes the group's children.
+     */
+    private inline fun List<ListEntry>.forEachNotificationEntry(
+        action: (NotificationEntry) -> Unit
+    ) {
+        forEach { entry ->
+            when (entry) {
+                is NotificationEntry -> action(entry)
+                is GroupEntry -> {
+                    action(entry.requireSummary)
+                    entry.children.forEach(action)
+                }
+                else -> error("Unhandled entry: $entry")
+            }
+        }
+    }
+}
\ No newline at end of file
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 b582a24..1a8d720 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
@@ -20,10 +20,8 @@
 import android.view.View
 import com.android.systemui.statusbar.notification.collection.GroupEntry
 import com.android.systemui.statusbar.notification.collection.ListEntry
-import com.android.systemui.statusbar.notification.collection.ShadeListBuilder
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
-import com.android.systemui.statusbar.phone.NotificationIconAreaController
 import com.android.systemui.util.traceSection
 import javax.inject.Inject
 
@@ -34,9 +32,9 @@
 class ShadeViewManager constructor(
     context: Context,
     listContainer: NotificationListContainer,
+    private val stackController: NotifStackController,
     logger: ShadeViewDifferLogger,
-    private val viewBarn: NotifViewBarn,
-    private val notificationIconAreaController: NotificationIconAreaController
+    private val viewBarn: NotifViewBarn
 ) {
     // We pass a shim view here because the listContainer may not actually have a view associated
     // with it and the differ never actually cares about the root node's view.
@@ -44,39 +42,39 @@
     private val specBuilder = NodeSpecBuilder(viewBarn)
     private val viewDiffer = ShadeViewDiffer(rootController, logger)
 
-    fun attach(listBuilder: ShadeListBuilder) =
-            listBuilder.setOnRenderListListener(::onNewNotifTree)
-
-    private fun onNewNotifTree(notifList: List<ListEntry>) {
-        traceSection("ShadeViewManager.onNewNotifTree") {
-            viewDiffer.applySpec(specBuilder.buildNodeSpec(rootController, notifList))
-            updateGroupCounts(notifList)
-            notificationIconAreaController.updateNotificationIcons(notifList)
-        }
+    /** Method for attaching this manager to the pipeline. */
+    fun attach(renderStageManager: RenderStageManager) {
+        renderStageManager.setViewRenderer(viewRenderer)
     }
 
-    private fun updateGroupCounts(notifList: List<ListEntry>) {
-        traceSection("ShadeViewManager.updateGroupCounts") {
-            notifList.asSequence().filterIsInstance<GroupEntry>().forEach { groupEntry ->
-                val controller = viewBarn.requireView(checkNotNull(groupEntry.summary))
-                val row = controller.view as ExpandableNotificationRow
-                row.setUntruncatedChildCount(groupEntry.untruncatedChildCount)
+    private val viewRenderer = object : NotifViewRenderer {
+
+        override fun onRenderList(notifList: List<ListEntry>) {
+            traceSection("ShadeViewManager.onRenderList") {
+                viewDiffer.applySpec(specBuilder.buildNodeSpec(rootController, notifList))
             }
         }
+
+        override fun getStackController(): NotifStackController = stackController
+
+        override fun getGroupController(group: GroupEntry): NotifGroupController =
+            viewBarn.requireGroupController(group.requireSummary)
+
+        override fun getRowController(entry: NotificationEntry): NotifRowController =
+            viewBarn.requireRowController(entry)
     }
 }
 
 class ShadeViewManagerFactory @Inject constructor(
     private val context: Context,
     private val logger: ShadeViewDifferLogger,
-    private val viewBarn: NotifViewBarn,
-    private val notificationIconAreaController: NotificationIconAreaController
+    private val viewBarn: NotifViewBarn
 ) {
-    fun create(listContainer: NotificationListContainer) =
-            ShadeViewManager(
-                    context,
-                    listContainer,
-                    logger,
-                    viewBarn,
-                    notificationIconAreaController)
+    fun create(listContainer: NotificationListContainer, stackController: NotifStackController) =
+        ShadeViewManager(
+            context,
+            listContainer,
+            stackController,
+            logger,
+            viewBarn)
 }
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 a19549c5..d25a2d3 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
@@ -31,7 +31,6 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.people.widget.PeopleSpaceWidgetManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -40,6 +39,7 @@
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.notification.AssistantFeedbackController;
 import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
@@ -116,7 +116,7 @@
     static NotificationEntryManager provideNotificationEntryManager(
             NotificationEntryManagerLogger logger,
             NotificationGroupManagerLegacy groupManager,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             Lazy<NotificationRowBinder> notificationRowBinderLazy,
             Lazy<NotificationRemoteInputManager> notificationRemoteInputManagerLazy,
             LeakDetector leakDetector,
@@ -126,7 +126,7 @@
         return new NotificationEntryManager(
                 logger,
                 groupManager,
-                featureFlags,
+                notifPipelineFlags,
                 notificationRowBinderLazy,
                 notificationRemoteInputManagerLazy,
                 leakDetector,
@@ -211,7 +211,7 @@
     static NotificationLogger provideNotificationLogger(
             NotificationListener notificationListener,
             @UiBackground Executor uiBgExecutor,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             NotificationVisibilityProvider visibilityProvider,
             NotificationEntryManager entryManager,
             NotifPipeline notifPipeline,
@@ -221,7 +221,7 @@
         return new NotificationLogger(
                 notificationListener,
                 uiBgExecutor,
-                featureFlags,
+                notifPipelineFlags,
                 visibilityProvider,
                 entryManager,
                 notifPipeline,
@@ -241,9 +241,9 @@
     @SysUISingleton
     @Provides
     static GroupMembershipManager provideGroupMembershipManager(
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             Lazy<NotificationGroupManagerLegacy> groupManagerLegacy) {
-        return featureFlags.isNewNotifPipelineRenderingEnabled()
+        return notifPipelineFlags.isNewPipelineEnabled()
                 ? new GroupMembershipManagerImpl()
                 : groupManagerLegacy.get();
     }
@@ -252,10 +252,10 @@
     @SysUISingleton
     @Provides
     static GroupExpansionManager provideGroupExpansionManager(
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             Lazy<GroupMembershipManager> groupMembershipManager,
             Lazy<NotificationGroupManagerLegacy> groupManagerLegacy) {
-        return featureFlags.isNewNotifPipelineRenderingEnabled()
+        return notifPipelineFlags.isNewPipelineEnabled()
                 ? new GroupExpansionManagerImpl(groupMembershipManager.get())
                 : groupManagerLegacy.get();
     }
@@ -280,10 +280,11 @@
     @Provides
     @SysUISingleton
     static CommonNotifCollection provideCommonNotifCollection(
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             Lazy<NotifPipeline> pipeline,
             NotificationEntryManager entryManager) {
-        return featureFlags.isNewNotifPipelineRenderingEnabled() ? pipeline.get() : entryManager;
+        return notifPipelineFlags.isNewPipelineEnabled()
+                ? pipeline.get() : entryManager;
     }
 
     /**
@@ -292,10 +293,10 @@
     @Provides
     @SysUISingleton
     static NotificationVisibilityProvider provideNotificationVisibilityProvider(
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             Lazy<NotificationVisibilityProviderImpl> newProvider,
             Lazy<LegacyNotificationVisibilityProvider> legacyProvider) {
-        return featureFlags.isNewNotifPipelineRenderingEnabled()
+        return notifPipelineFlags.isNewPipelineEnabled()
                 ? newProvider.get()
                 : legacyProvider.get();
     }
@@ -306,10 +307,10 @@
     @Provides
     @SysUISingleton
     static NotifShadeEventSource provideNotifShadeEventSource(
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             Lazy<ShadeEventCoordinator> shadeEventCoordinatorLazy,
             Lazy<LegacyNotificationPresenterExtensions> legacyNotificationPresenterExtensionsLazy) {
-        return featureFlags.isNewNotifPipelineRenderingEnabled()
+        return notifPipelineFlags.isNewPipelineEnabled()
                 ? shadeEventCoordinatorLazy.get()
                 : legacyNotificationPresenterExtensionsLazy.get();
     }
@@ -321,7 +322,7 @@
     @Provides
     @SysUISingleton
     static OnUserInteractionCallback provideOnUserInteractionCallback(
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             HeadsUpManager headsUpManager,
             StatusBarStateController statusBarStateController,
             Lazy<NotifCollection> notifCollection,
@@ -330,7 +331,7 @@
             NotificationEntryManager entryManager,
             VisualStabilityManager visualStabilityManager,
             Lazy<GroupMembershipManager> groupMembershipManagerLazy) {
-        return featureFlags.isNewNotifPipelineRenderingEnabled()
+        return notifPipelineFlags.isNewPipelineEnabled()
                 ? new OnUserInteractionCallbackImpl(
                         visibilityProvider.get(),
                         notifCollection.get(),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
index 2f496dd..a59d421 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsController.kt
@@ -21,6 +21,7 @@
 import com.android.systemui.statusbar.NotificationPresenter
 import com.android.systemui.statusbar.notification.NotificationActivityStarter
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
 import com.android.systemui.statusbar.phone.StatusBar
 import com.android.wm.shell.bubbles.Bubbles
@@ -40,6 +41,7 @@
         bubblesOptional: Optional<Bubbles>,
         presenter: NotificationPresenter,
         listContainer: NotificationListContainer,
+        stackController: NotifStackController,
         notificationActivityStarter: NotificationActivityStarter,
         bindRowCallback: NotificationRowBinderImpl.BindRowCallback
     )
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 757f68a..212c342e 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
@@ -20,10 +20,10 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.people.widget.PeopleSpaceWidgetManager
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption
-import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.statusbar.NotificationListener
 import com.android.systemui.statusbar.NotificationPresenter
 import com.android.systemui.statusbar.notification.AnimatedImageNotificationManager
+import com.android.systemui.statusbar.notification.NotifPipelineFlags
 import com.android.systemui.statusbar.notification.NotificationActivityStarter
 import com.android.systemui.statusbar.notification.NotificationClicker
 import com.android.systemui.statusbar.notification.NotificationEntryManager
@@ -34,6 +34,7 @@
 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.legacy.NotificationGroupManagerLegacy
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController
 import com.android.systemui.statusbar.notification.interruption.HeadsUpController
 import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder
 import com.android.systemui.statusbar.notification.row.NotifBindPipelineInitializer
@@ -59,7 +60,7 @@
  */
 @SysUISingleton
 class NotificationsControllerImpl @Inject constructor(
-    private val featureFlags: FeatureFlags,
+    private val notifPipelineFlags: NotifPipelineFlags,
     private val notificationListener: NotificationListener,
     private val entryManager: NotificationEntryManager,
     private val legacyRanker: NotificationRankingManager,
@@ -85,6 +86,7 @@
         bubblesOptional: Optional<Bubbles>,
         presenter: NotificationPresenter,
         listContainer: NotificationListContainer,
+        stackController: NotifStackController,
         notificationActivityStarter: NotificationActivityStarter,
         bindRowCallback: NotificationRowBinderImpl.BindRowCallback
     ) {
@@ -112,10 +114,11 @@
             newNotifPipeline.get().initialize(
                     notificationListener,
                     notificationRowBinder,
-                    listContainer)
+                    listContainer,
+                    stackController)
         }
 
-        if (featureFlags.isNewNotifPipelineRenderingEnabled) {
+        if (notifPipelineFlags.isNewPipelineEnabled()) {
             targetSdkResolver.initialize(notifPipeline.get())
             // TODO
         } else {
@@ -152,8 +155,14 @@
     }
 
     override fun resetUserExpandedStates() {
-        for (entry in entryManager.visibleNotifications) {
-            entry.resetUserExpansion()
+        if (notifPipelineFlags.isNewPipelineEnabled()) {
+            for (entry in notifPipeline.get().allNotifs) {
+                entry.resetUserExpansion()
+            }
+        } else {
+            for (entry in entryManager.visibleNotifications) {
+                entry.resetUserExpansion()
+            }
         }
     }
 
@@ -167,9 +176,12 @@
         }
     }
 
-    override fun getActiveNotificationsCount(): Int {
-        return entryManager.activeNotificationsCount
-    }
+    override fun getActiveNotificationsCount(): Int =
+        if (notifPipelineFlags.isNewPipelineEnabled()) {
+            notifPipeline.get().getShadeListCount()
+        } else {
+            entryManager.activeNotificationsCount
+        }
 
     companion object {
         // NOTE: The new pipeline is always active, even if the old pipeline is *rendering*.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
index eadf5ac..1c9af11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/init/NotificationsControllerStub.kt
@@ -22,6 +22,7 @@
 import com.android.systemui.statusbar.NotificationPresenter
 import com.android.systemui.statusbar.notification.NotificationActivityStarter
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer
 import com.android.systemui.statusbar.phone.StatusBar
 import com.android.wm.shell.bubbles.Bubbles
@@ -42,6 +43,7 @@
         bubblesOptional: Optional<Bubbles>,
         presenter: NotificationPresenter,
         listContainer: NotificationListContainer,
+        stackController: NotifStackController,
         notificationActivityStarter: NotificationActivityStarter,
         bindRowCallback: NotificationRowBinderImpl.BindRowCallback
     ) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
index 993e38d..bd1f609 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationLogger.java
@@ -34,11 +34,11 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.dagger.qualifiers.UiBackground;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -75,7 +75,7 @@
     // Dependencies:
     private final NotificationListenerService mNotificationListener;
     private final Executor mUiBgExecutor;
-    private final FeatureFlags mFeatureFlags;
+    private final NotifPipelineFlags mNotifPipelineFlags;
     private final NotificationVisibilityProvider mVisibilityProvider;
     private final NotificationEntryManager mEntryManager;
     private final NotifPipeline mNotifPipeline;
@@ -175,7 +175,7 @@
     };
 
     private List<NotificationEntry> getVisibleNotifications() {
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             return mNotifPipeline.getFlatShadeList();
         } else {
             return mEntryManager.getVisibleNotifications();
@@ -218,7 +218,7 @@
      */
     public NotificationLogger(NotificationListener notificationListener,
             @UiBackground Executor uiBgExecutor,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             NotificationVisibilityProvider visibilityProvider,
             NotificationEntryManager entryManager,
             NotifPipeline notifPipeline,
@@ -227,7 +227,7 @@
             NotificationPanelLogger notificationPanelLogger) {
         mNotificationListener = notificationListener;
         mUiBgExecutor = uiBgExecutor;
-        mFeatureFlags = featureFlags;
+        mNotifPipelineFlags = notifPipelineFlags;
         mVisibilityProvider = visibilityProvider;
         mEntryManager = entryManager;
         mNotifPipeline = notifPipeline;
@@ -238,7 +238,7 @@
         // Not expected to be destroyed, don't need to unsubscribe
         statusBarStateController.addCallback(this);
 
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             registerNewPipelineListener();
         } else {
             registerLegacyListener();
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 b0ee37b..2fbd212 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
@@ -23,7 +23,6 @@
 import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP;
 import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
 
-import android.Manifest;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
@@ -50,12 +49,12 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.ServiceManager;
-import android.permission.PermissionManager;
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.Pair;
@@ -94,6 +93,7 @@
 import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
 import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
 import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -133,7 +133,8 @@
  * the group summary (which contains 1 or more child notifications).
  */
 public class ExpandableNotificationRow extends ActivatableNotificationView
-        implements PluginListener<NotificationMenuRowPlugin>, SwipeableView {
+        implements PluginListener<NotificationMenuRowPlugin>, SwipeableView,
+        NotificationFadeAware.FadeOptimizedNotification {
 
     private static final boolean DEBUG = false;
     private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
@@ -146,6 +147,7 @@
     private boolean mUpdateBackgroundOnUpdate;
     private boolean mNotificationTranslationFinished = false;
     private boolean mIsSnoozed;
+    private boolean mIsFaded;
 
     /**
      * Listener for when {@link ExpandableNotificationRow} is laid out.
@@ -814,6 +816,13 @@
         mChildrenContainer.setUntruncatedChildCount(childCount);
     }
 
+    /** Called after children have been attached to set the expansion states */
+    public void resetChildSystemExpandedStates() {
+        if (isSummaryWithChildren()) {
+            mChildrenContainer.updateExpansionStates();
+        }
+    }
+
     /**
      * Add a child notification to this view.
      *
@@ -2341,6 +2350,7 @@
             onExpansionChanged(false /* userAction */, wasExpanded);
             if (mIsSummaryWithChildren) {
                 mChildrenContainer.updateGroupOverflow();
+                resetChildSystemExpandedStates();
             }
         }
     }
@@ -2776,17 +2786,112 @@
             // alphas are reset
             if (mChildrenContainer != null) {
                 mChildrenContainer.setAlpha(1.0f);
-                mChildrenContainer.setLayerType(LAYER_TYPE_NONE, null);
             }
             for (NotificationContentView l : mLayouts) {
                 l.setAlpha(1.0f);
-                l.setLayerType(LAYER_TYPE_NONE, null);
+            }
+            if (FADE_LAYER_OPTIMIZATION_ENABLED) {
+                setNotificationFaded(false);
+            } else {
+                setNotificationFadedOnChildren(false);
             }
         } else {
             setHeadsUpAnimatingAway(false);
         }
     }
 
+    /** Gets the last value set with {@link #setNotificationFaded(boolean)} */
+    @Override
+    public boolean isNotificationFaded() {
+        return mIsFaded;
+    }
+
+    /**
+     * This class needs to delegate the faded state set on it by
+     * {@link com.android.systemui.statusbar.notification.stack.ViewState} to its children.
+     * Having each notification use layerType of HARDWARE anytime it fades in/out can result in
+     * extremely large layers (in the case of groups, it can even exceed the device height).
+     * Because these large renders can cause serious jank when rendering, we instead have
+     * notifications return false from {@link #hasOverlappingRendering()} and delegate the
+     * layerType to child views which really need it in order to render correctly, such as icon
+     * views or the conversation face pile.
+     *
+     * Another compounding factor for notifications is that we change clipping on each frame of the
+     * animation, so the hardware layer isn't able to do any caching at the top level, but the
+     * individual elements we render with hardware layers (e.g. icons) cache wonderfully because we
+     * never invalidate them.
+     */
+    @Override
+    public void setNotificationFaded(boolean faded) {
+        mIsFaded = faded;
+        if (childrenRequireOverlappingRendering()) {
+            // == Simple Scenario ==
+            // If a child (like remote input) needs this to have overlapping rendering, then set
+            // the layerType of this view and reset the children to render as if the notification is
+            // not fading.
+            NotificationFadeAware.setLayerTypeForFaded(this, faded);
+            setNotificationFadedOnChildren(false);
+        } else {
+            // == Delegating Scenario ==
+            // This is the new normal for alpha: Explicitly reset this view's layer type to NONE,
+            // and require that all children use their own hardware layer if they have bad
+            // overlapping rendering.
+            NotificationFadeAware.setLayerTypeForFaded(this, false);
+            setNotificationFadedOnChildren(faded);
+        }
+    }
+
+    /** Private helper for iterating over the layouts and children containers to set faded state */
+    private void setNotificationFadedOnChildren(boolean faded) {
+        delegateNotificationFaded(mChildrenContainer, faded);
+        for (NotificationContentView layout : mLayouts) {
+            delegateNotificationFaded(layout, faded);
+        }
+    }
+
+    private static void delegateNotificationFaded(@Nullable View view, boolean faded) {
+        if (FADE_LAYER_OPTIMIZATION_ENABLED && view instanceof NotificationFadeAware) {
+            ((NotificationFadeAware) view).setNotificationFaded(faded);
+        } else {
+            NotificationFadeAware.setLayerTypeForFaded(view, faded);
+        }
+    }
+
+    /**
+     * Only declare overlapping rendering if independent children of the view require it.
+     */
+    @Override
+    public boolean hasOverlappingRendering() {
+        return super.hasOverlappingRendering() && childrenRequireOverlappingRendering();
+    }
+
+    /**
+     * Because RemoteInputView is designed to be an opaque view that overlaps the Actions row, the
+     * row should require overlapping rendering to ensure that the overlapped view doesn't bleed
+     * through when alpha fading.
+     *
+     * Note that this currently works for top-level notifications which squish their height down
+     * while collapsing the shade, but does not work for children inside groups, because the
+     * accordion affect does not apply to those views, so super.hasOverlappingRendering() will
+     * always return false to avoid the clipping caused when the view's measured height is less than
+     * the 'actual height'.
+     */
+    private boolean childrenRequireOverlappingRendering() {
+        if (!FADE_LAYER_OPTIMIZATION_ENABLED) {
+            return true;
+        }
+        // The colorized background is another layer with which all other elements overlap
+        if (getEntry().getSbn().getNotification().isColorized()) {
+            return true;
+        }
+        // Check if the showing layout has a need for overlapping rendering.
+        // NOTE: We could check both public and private layouts here, but becuause these states
+        //  don't animate well, there are bigger visual artifacts if we start changing the shown
+        //  layout during shade expansion.
+        NotificationContentView showingLayout = getShowingLayout();
+        return showingLayout != null && showingLayout.requireRowToHaveOverlappingRendering();
+    }
+
     @Override
     public int getExtraBottomPadding() {
         if (mIsSummaryWithChildren && isGroupExpanded()) {
@@ -3205,11 +3310,8 @@
         return getCurrentBottomRoundness() == 0.0f && getCurrentTopRoundness() == 0.0f;
     }
 
-    //TODO: this logic can't depend on layout if we are recycling!
     public boolean isMediaRow() {
-        return getExpandedContentView() != null
-                && getExpandedContentView().findViewById(
-                com.android.internal.R.id.media_actions) != null;
+        return mEntry.getSbn().getNotification().isMediaNotification();
     }
 
     public boolean isTopLevelChild() {
@@ -3330,44 +3432,47 @@
     }
 
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+        IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
         // Skip super call; dump viewState ourselves
         pw.println("Notification: " + mEntry.getKey());
-        DumpUtilsKt.withIndenting(pw, ipw -> {
-            ipw.print("visibility: " + getVisibility());
-            ipw.print(", alpha: " + getAlpha());
-            ipw.print(", translation: " + getTranslation());
-            ipw.print(", removed: " + isRemoved());
-            ipw.print(", expandAnimationRunning: " + mExpandAnimationRunning);
+        DumpUtilsKt.withIncreasedIndent(pw, () -> {
+            pw.print("visibility: " + getVisibility());
+            pw.print(", alpha: " + getAlpha());
+            pw.print(", translation: " + getTranslation());
+            pw.print(", removed: " + isRemoved());
+            pw.print(", expandAnimationRunning: " + mExpandAnimationRunning);
             NotificationContentView showingLayout = getShowingLayout();
-            ipw.print(", privateShowing: " + (showingLayout == mPrivateLayout));
-            ipw.println();
-            showingLayout.dump(fd, ipw, args);
+            pw.print(", privateShowing: " + (showingLayout == mPrivateLayout));
+            pw.println();
+            showingLayout.dump(fd, pw, args);
 
             if (getViewState() != null) {
-                getViewState().dump(fd, ipw, args);
-                ipw.println();
+                getViewState().dump(fd, pw, args);
+                pw.println();
             } else {
-                ipw.println("no viewState!!!");
+                pw.println("no viewState!!!");
             }
 
             if (mIsSummaryWithChildren) {
-                ipw.println();
-                ipw.print("ChildrenContainer");
-                ipw.print(" visibility: " + mChildrenContainer.getVisibility());
-                ipw.print(", alpha: " + mChildrenContainer.getAlpha());
-                ipw.print(", translationY: " + mChildrenContainer.getTranslationY());
-                ipw.println();
+                pw.println();
+                pw.print("ChildrenContainer");
+                pw.print(" visibility: " + mChildrenContainer.getVisibility());
+                pw.print(", alpha: " + mChildrenContainer.getAlpha());
+                pw.print(", translationY: " + mChildrenContainer.getTranslationY());
+                pw.println();
                 List<ExpandableNotificationRow> notificationChildren = getAttachedChildren();
-                ipw.println("Children: " + notificationChildren.size());
-                ipw.print("{");
-                ipw.increaseIndent();
+                pw.println("Children: " + notificationChildren.size());
+                pw.print("{");
+                pw.increaseIndent();
                 for (ExpandableNotificationRow child : notificationChildren) {
-                    ipw.println();
-                    child.dump(fd, ipw, args);
+                    pw.println();
+                    child.dump(fd, pw, args);
                 }
-                ipw.decreaseIndent();
-                ipw.println("}");
+                pw.decreaseIndent();
+                pw.println("}");
+            } else if (mPrivateLayout != null) {
+                mPrivateLayout.dumpSmartReplies(pw);
             }
         });
     }
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 0b29ae5..3d35d0e 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
@@ -20,6 +20,8 @@
 import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
 
+import android.util.Log;
+import android.util.Pair;
 import android.view.View;
 import android.view.ViewGroup;
 
@@ -36,6 +38,7 @@
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
 import com.android.systemui.statusbar.notification.collection.render.NodeController;
+import com.android.systemui.statusbar.notification.collection.render.NotifViewController;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
 import com.android.systemui.statusbar.notification.row.dagger.AppName;
@@ -58,7 +61,8 @@
  * Controller for {@link ExpandableNotificationRow}.
  */
 @NotificationRowScope
-public class ExpandableNotificationRowController implements NodeController {
+public class ExpandableNotificationRowController implements NotifViewController {
+    private static final String TAG = "NotifRowController";
     private final ExpandableNotificationRow mView;
     private final NotificationListContainer mListContainer;
     private final RemoteInputViewSubcomponent.Factory mRemoteInputViewSubcomponentFactory;
@@ -241,7 +245,7 @@
     public void addChildAt(NodeController child, int index) {
         ExpandableNotificationRow childView = (ExpandableNotificationRow) child.getView();
 
-        mView.addChildNotification((ExpandableNotificationRow) child.getView());
+        mView.addChildNotification((ExpandableNotificationRow) child.getView(), index);
         mListContainer.notifyGroupChildAdded(childView);
     }
 
@@ -267,4 +271,28 @@
         final List<ExpandableNotificationRow> mChildren = mView.getAttachedChildren();
         return mChildren != null ? mChildren.size() : 0;
     }
+
+    @Override
+    public void setUntruncatedChildCount(int childCount) {
+        if (mView.isSummaryWithChildren()) {
+            mView.setUntruncatedChildCount(childCount);
+        } else {
+            Log.w(TAG, "Called setUntruncatedChildCount(" + childCount + ") on a leaf row");
+        }
+    }
+
+    @Override
+    public void setSystemExpanded(boolean systemExpanded) {
+        mView.setSystemExpanded(systemExpanded);
+    }
+
+    @Override
+    public void setLastAudiblyAlertedMs(long lastAudiblyAlertedMs) {
+        mView.setLastAudiblyAlertedMs(lastAudiblyAlertedMs);
+    }
+
+    @Override
+    public void showFeedbackIcon(boolean show, Pair<Integer, Integer> feedbackResources) {
+        mView.showFeedbackIcon(show, feedbackResources);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index fa2c1ee..4b3d6f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -22,6 +22,7 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.util.IndentingPrintWriter;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -743,15 +744,16 @@
     }
 
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+        IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
         pw.println(getClass().getSimpleName());
-        DumpUtilsKt.withIndenting(pw, ipw -> {
+        DumpUtilsKt.withIncreasedIndent(pw, () -> {
             ExpandableViewState viewState = getViewState();
             if (viewState == null) {
-                ipw.println("no viewState!!!");
+                pw.println("no viewState!!!");
             } else {
-                viewState.dump(fd, ipw, args);
-                ipw.println();
+                viewState.dump(fd, pw, args);
+                pw.println();
             }
         });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
index b27a40a..e8e6e31 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/FooterView.java
@@ -20,6 +20,7 @@
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.util.AttributeSet;
+import android.util.IndentingPrintWriter;
 import android.view.View;
 
 import com.android.systemui.R;
@@ -49,14 +50,15 @@
     }
 
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+        IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
         super.dump(fd, pw, args);
-        DumpUtilsKt.withIndenting(pw, ipw -> {
-            ipw.println("visibility: " + DumpUtilsKt.visibilityString(getVisibility()));
-            ipw.println("manageButton showHistory: " + mShowHistory);
-            ipw.println("manageButton visibility: "
+        DumpUtilsKt.withIncreasedIndent(pw, () -> {
+            pw.println("visibility: " + DumpUtilsKt.visibilityString(getVisibility()));
+            pw.println("manageButton showHistory: " + mShowHistory);
+            pw.println("manageButton visibility: "
                     + DumpUtilsKt.visibilityString(mDismissButton.getVisibility()));
-            ipw.println("dismissButton visibility: "
+            pw.println("dismissButton visibility: "
                     + DumpUtilsKt.visibilityString(mDismissButton.getVisibility()));
         });
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
index caba3ac..c661408 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
@@ -28,6 +28,7 @@
 
 import com.android.internal.widget.ConversationLayout;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
 
 /**
  * A hybrid view which may contain information about one ore more conversations.
@@ -138,4 +139,14 @@
         lp.height = size;
         view.setLayoutParams(lp);
     }
+
+    /**
+     * Apply the faded state as a layer type change to the face pile view which needs to have
+     * overlapping contents render precisely.
+     */
+    @Override
+    public void setNotificationFaded(boolean faded) {
+        super.setNotificationFaded(faded);
+        NotificationFadeAware.setLayerTypeForFaded(mConversationFacePile, faded);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java
index bc2adac3..c0d85a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java
@@ -28,13 +28,14 @@
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.TransformableView;
 import com.android.systemui.statusbar.ViewTransformationHelper;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
 import com.android.systemui.statusbar.notification.TransformState;
 
 /**
  * A hybrid view which may contain information about one ore more notifications.
  */
 public class HybridNotificationView extends AlphaOptimizedLinearLayout
-        implements TransformableView {
+        implements TransformableView, NotificationFadeAware {
 
     protected final ViewTransformationHelper mTransformationHelper = new ViewTransformationHelper();
     protected TextView mTitleView;
@@ -148,4 +149,7 @@
         setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
         mTransformationHelper.setVisible(visible);
     }
+
+    @Override
+    public void setNotificationFaded(boolean faded) {}
 }
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 4568470..438992e 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
@@ -27,6 +27,7 @@
 import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.AttributeSet;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.Pair;
 import android.view.LayoutInflater;
@@ -45,6 +46,7 @@
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
@@ -72,7 +74,7 @@
  * expanded and heads up layout. This class is responsible for clipping the content and and
  * switching between the expanded, contracted and the heads up view depending on its clipped size.
  */
-public class NotificationContentView extends FrameLayout {
+public class NotificationContentView extends FrameLayout implements NotificationFadeAware {
 
     private static final String TAG = "NotificationContentView";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -1289,8 +1291,8 @@
                     result.mView = riv;
                     // Create a new controller for the view. The lifetime of the controller is 1:1
                     // with that of the view.
-                    RemoteInputViewSubcomponent subcomponent =
-                            mRemoteInputSubcomponentFactory.create(result.mView);
+                    RemoteInputViewSubcomponent subcomponent = mRemoteInputSubcomponentFactory
+                            .create(result.mView, mRemoteInputController);
                     result.mController = subcomponent.getController();
                     result.mView.setController(result.mController);
                 } else {
@@ -1311,8 +1313,9 @@
                     Notification.Action[] actions = entry.getSbn().getNotification().actions;
                     if (existingPendingIntent != null) {
                         result.mView.setPendingIntent(existingPendingIntent);
+                        result.mController.setPendingIntent(existingPendingIntent);
                     }
-                    if (result.mView.updatePendingIntentFromActions(actions)) {
+                    if (result.mController.updatePendingIntentFromActions(actions)) {
                         if (!result.mView.isActive()) {
                             result.mView.focus();
                         }
@@ -2004,6 +2007,22 @@
         pw.println();
     }
 
+    /** Add any existing SmartReplyView to the dump */
+    public void dumpSmartReplies(IndentingPrintWriter pw) {
+        if (mHeadsUpSmartReplyView != null) {
+            pw.println("HeadsUp SmartReplyView:");
+            pw.increaseIndent();
+            mHeadsUpSmartReplyView.dump(pw);
+            pw.decreaseIndent();
+        }
+        if (mExpandedSmartReplyView != null) {
+            pw.println("Expanded SmartReplyView:");
+            pw.increaseIndent();
+            mExpandedSmartReplyView.dump(pw);
+            pw.decreaseIndent();
+        }
+    }
+
     public RemoteInputView getExpandedRemoteInput() {
         return mExpandedRemoteInput;
     }
@@ -2027,6 +2046,41 @@
         return Notification.COLOR_INVALID;
     }
 
+    /**
+     * Delegate the faded state to the notification content views which actually
+     * need to have overlapping contents render precisely.
+     */
+    @Override
+    public void setNotificationFaded(boolean faded) {
+        if (mContractedWrapper != null) {
+            mContractedWrapper.setNotificationFaded(faded);
+        }
+        if (mHeadsUpWrapper != null) {
+            mHeadsUpWrapper.setNotificationFaded(faded);
+        }
+        if (mExpandedWrapper != null) {
+            mExpandedWrapper.setNotificationFaded(faded);
+        }
+        if (mSingleLineView != null) {
+            mSingleLineView.setNotificationFaded(faded);
+        }
+    }
+
+    /**
+     * @return true if a visible view has a remote input active, as this requires that the entire
+     * row report that it has overlapping rendering.
+     */
+    public boolean requireRowToHaveOverlappingRendering() {
+        // This inexpensive check is done on both states to avoid state invalidating the result.
+        if (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive()) {
+            return true;
+        }
+        if (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive()) {
+            return true;
+        }
+        return false;
+    }
+
     public void setRemoteInputViewSubcomponentFactory(RemoteInputViewSubcomponent.Factory factory) {
         mRemoteInputSubcomponentFactory = factory;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
index 12e94cb..bb43b95 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
@@ -21,6 +21,7 @@
 import com.android.internal.widget.CachingIconView
 import com.android.internal.widget.CallLayout
 import com.android.systemui.R
+import com.android.systemui.statusbar.notification.NotificationFadeAware
 import com.android.systemui.statusbar.notification.NotificationUtils
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 
@@ -37,6 +38,7 @@
             NotificationUtils.getFontScaledHeight(ctx, R.dimen.notification_max_height)
     private val callLayout: CallLayout = view as CallLayout
 
+    private lateinit var conversationIconContainer: View
     private lateinit var conversationIconView: CachingIconView
     private lateinit var conversationBadgeBg: View
     private lateinit var expandBtn: View
@@ -45,6 +47,8 @@
 
     private fun resolveViews() {
         with(callLayout) {
+            conversationIconContainer =
+                    requireViewById(com.android.internal.R.id.conversation_icon_container)
             conversationIconView = requireViewById(com.android.internal.R.id.conversation_icon)
             conversationBadgeBg =
                     requireViewById(com.android.internal.R.id.conversation_icon_badge_bg)
@@ -82,4 +86,14 @@
     }
 
     override fun getMinLayoutHeight(): Int = minHeightWithActions
+
+    /**
+     * Apply the faded state as a layer type change to the face pile view which needs to have
+     * overlapping contents render precisely.
+     */
+    override fun setNotificationFaded(faded: Boolean) {
+        // Do not call super
+        NotificationFadeAware.setLayerTypeForFaded(expandBtn, faded)
+        NotificationFadeAware.setLayerTypeForFaded(conversationIconContainer, faded)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
index 3ef5b665..e136055 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
@@ -23,6 +23,7 @@
 import com.android.internal.widget.ConversationLayout
 import com.android.internal.widget.MessagingLinearLayout
 import com.android.systemui.R
+import com.android.systemui.statusbar.notification.NotificationFadeAware
 import com.android.systemui.statusbar.notification.NotificationUtils
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 import com.android.systemui.statusbar.notification.row.wrapper.NotificationMessagingTemplateViewWrapper.setCustomImageMessageTransform
@@ -42,6 +43,7 @@
     )
     private val conversationLayout: ConversationLayout = view as ConversationLayout
 
+    private lateinit var conversationIconContainer: View
     private lateinit var conversationIconView: CachingIconView
     private lateinit var conversationBadgeBg: View
     private lateinit var expandBtn: View
@@ -59,6 +61,8 @@
         messagingLinearLayout = conversationLayout.messagingLinearLayout
         imageMessageContainer = conversationLayout.imageMessageContainer
         with(conversationLayout) {
+            conversationIconContainer =
+                    requireViewById(com.android.internal.R.id.conversation_icon_container)
             conversationIconView = requireViewById(com.android.internal.R.id.conversation_icon)
             conversationBadgeBg =
                     requireViewById(com.android.internal.R.id.conversation_icon_badge_bg)
@@ -136,4 +140,10 @@
                 minHeightWithActions
             else
                 super.getMinLayoutHeight()
+
+    override fun setNotificationFaded(faded: Boolean) {
+        // Do not call super
+        NotificationFadeAware.setLayerTypeForFaded(expandBtn, faded)
+        NotificationFadeAware.setLayerTypeForFaded(conversationIconContainer, faded)
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
index 4c9c2f9..fdff12d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java
@@ -22,6 +22,7 @@
 
 import com.android.internal.graphics.ColorUtils;
 import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
@@ -86,4 +87,14 @@
     public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
         return true;
     }
+
+    /**
+     * Apply the faded state as a layer type change to the custom view which needs to have
+     * overlapping contents render precisely.
+     */
+    @Override
+    public void setNotificationFaded(boolean faded) {
+        super.setNotificationFaded(faded);
+        NotificationFadeAware.setLayerTypeForFaded(mView, faded);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
index 8c6fa02..3159539 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
@@ -20,6 +20,7 @@
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
 /**
@@ -67,4 +68,14 @@
         }
         super.onContentUpdated(row);
     }
+
+    /**
+     * Apply the faded state as a layer type change to the custom view which needs to have
+     * overlapping contents render precisely.
+     */
+    @Override
+    public void setNotificationFaded(boolean faded) {
+        super.setNotificationFaded(faded);
+        NotificationFadeAware.setLayerTypeForFaded(mWrappedView, faded);
+    }
 }
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 7630191..6c3e0d2 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
@@ -42,6 +42,7 @@
 import com.android.settingslib.Utils;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
 import com.android.systemui.statusbar.notification.TransformState;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 
@@ -395,4 +396,13 @@
      */
     public void setRecentlyAudiblyAlerted(boolean audiblyAlerted) {
     }
+
+    /**
+     * Apply the faded state as a layer type change to the views which need to have overlapping
+     * contents render precisely.
+     */
+    public void setNotificationFaded(boolean faded) {
+        NotificationFadeAware.setLayerTypeForFaded(getIcon(), faded);
+        NotificationFadeAware.setLayerTypeForFaded(getExpandButton(), faded);
+    }
 }
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 a472710..1875124 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
@@ -38,6 +38,7 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.CrossFadeHelper;
 import com.android.systemui.statusbar.NotificationGroupingUtil;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
 import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -51,7 +52,8 @@
 /**
  * A container containing child notifications
  */
-public class NotificationChildrenContainer extends ViewGroup {
+public class NotificationChildrenContainer extends ViewGroup
+        implements NotificationFadeAware {
 
     @VisibleForTesting
     static final int NUMBER_OF_CHILDREN_WHEN_COLLAPSED = 2;
@@ -111,6 +113,7 @@
     private int mCurrentHeaderTranslation = 0;
     private float mHeaderVisibleAmount = 1.0f;
     private int mUntruncatedChildCount;
+    private boolean mContainingNotificationIsFaded = false;
 
     public NotificationChildrenContainer(Context context) {
         this(context, null);
@@ -277,6 +280,7 @@
         mDividers.add(newIndex, divider);
 
         row.setContentTransformationAmount(0, false /* isLastChild */);
+        row.setNotificationFaded(mContainingNotificationIsFaded);
         // It doesn't make sense to keep old animations around, lets cancel them!
         ExpandableViewState viewState = row.getViewState();
         if (viewState != null) {
@@ -301,6 +305,7 @@
         });
 
         row.setSystemChildExpanded(false);
+        row.setNotificationFaded(false);
         row.setUserLocked(false);
         if (!row.isRemoved()) {
             mGroupingUtil.restoreChildNotification(row);
@@ -473,7 +478,8 @@
         return result;
     }
 
-    private void updateExpansionStates() {
+    /** To be called any time the rows have been updated */
+    public void updateExpansionStates() {
         if (mChildrenExpanded || mUserLocked) {
             // we don't modify it the group is expanded or if we are expanding it
             return;
@@ -1308,4 +1314,18 @@
             mNotificationHeaderWrapperLowPriority.setRecentlyAudiblyAlerted(audiblyAlertedRecently);
         }
     }
+
+    @Override
+    public void setNotificationFaded(boolean faded) {
+        mContainingNotificationIsFaded = faded;
+        if (mNotificationHeaderWrapper != null) {
+            mNotificationHeaderWrapper.setNotificationFaded(faded);
+        }
+        if (mNotificationHeaderWrapperLowPriority != null) {
+            mNotificationHeaderWrapperLowPriority.setNotificationFaded(faded);
+        }
+        for (ExpandableNotificationRow child : mAttachedChildren) {
+            child.setNotificationFaded(faded);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
index 408c457..88198f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
@@ -22,10 +22,10 @@
 import android.view.View
 import com.android.internal.annotations.VisibleForTesting
 import com.android.systemui.R
-import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.media.KeyguardMediaController
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.NotifPipelineFlags
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
 import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController
 import com.android.systemui.statusbar.notification.collection.render.ShadeViewManager
@@ -54,12 +54,12 @@
  * TODO: Move remaining sections logic from NSSL into this class.
  */
 class NotificationSectionsManager @Inject internal constructor(
-    private val featureFlags: FeatureFlags,
     private val statusBarStateController: StatusBarStateController,
     private val configurationController: ConfigurationController,
     private val keyguardMediaController: KeyguardMediaController,
     private val sectionsFeatureManager: NotificationSectionsFeatureManager,
     private val logger: NotificationSectionsLogger,
+    private val notifPipelineFlags: NotifPipelineFlags,
     @IncomingHeader private val incomingHeaderController: SectionHeaderController,
     @PeopleHeader private val peopleHeaderController: SectionHeaderController,
     @AlertingHeader private val alertingHeaderController: SectionHeaderController,
@@ -201,7 +201,7 @@
                 override var targetPosition: Int? = null
 
                 override fun adjustViewPosition() {
-                    featureFlags.checkLegacyPipelineEnabled()
+                    notifPipelineFlags.checkLegacyPipelineEnabled()
                     val target = targetPosition
                     val current = currentPosition
                     if (target == null) {
@@ -228,7 +228,7 @@
     private fun <T : StackScrollerDecorView> decorViewHeaderState(
         header: T
     ): SectionUpdateState<T> {
-        featureFlags.checkLegacyPipelineEnabled()
+        notifPipelineFlags.checkLegacyPipelineEnabled()
         val inner = expandableViewHeaderState(header)
         return object : SectionUpdateState<T> by inner {
             override fun adjustViewPosition() {
@@ -245,7 +245,7 @@
      * bookkeeping and adds/moves/removes section headers if appropriate.
      */
     fun updateSectionBoundaries(reason: String) {
-        featureFlags.checkLegacyPipelineEnabled()
+        notifPipelineFlags.checkLegacyPipelineEnabled()
         if (!isUsingMultipleSections) {
             return
         }
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 a97a54a..44e3718 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
@@ -47,6 +47,7 @@
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.AttributeSet;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.Pair;
@@ -678,7 +679,7 @@
         // TODO: move this logic to controller, which will invoke updateFooterView directly
         boolean showDismissView = mClearAllEnabled &&
                 mController.hasActiveClearableNotifications(ROWS_ALL);
-        boolean showFooterView = (showDismissView || getVisibleNotificationCount() > 0)
+        boolean showFooterView = (showDismissView || mController.getVisibleNotificationCount() > 0)
                 && mIsCurrentUserSetup  // see: b/193149550
                 && mStatusBarState != StatusBarState.KEYGUARD
                 && !mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()
@@ -1173,20 +1174,6 @@
         }
     }
 
-    /**
-     * Returns best effort count of visible notifications.
-     */
-    public int getVisibleNotificationCount() {
-        int count = 0;
-        for (int i = 0; i < getChildCount(); i++) {
-            final View child = getChildAt(i);
-            if (child.getVisibility() != View.GONE && child instanceof ExpandableNotificationRow) {
-                count++;
-            }
-        }
-        return count;
-    }
-
     @ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
     private boolean isCurrentlyAnimating() {
         return mStateAnimator.isRunning();
@@ -1458,7 +1445,7 @@
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private float getAppearEndPosition() {
         int appearPosition = 0;
-        int visibleNotifCount = getVisibleNotificationCount();
+        int visibleNotifCount = mController.getVisibleNotificationCount();
         if (mEmptyShadeView.getVisibility() == GONE && visibleNotifCount > 0) {
             if (isHeadsUpTransition()
                     || (mInHeadsUpPinnedMode && !mAmbientState.isDozing())) {
@@ -4642,7 +4629,7 @@
     }
 
     private void ensureRemovedFromTransientContainer(View v) {
-        if (v.getParent() == this && v instanceof SectionHeaderView) {
+        if (v.getParent() == this && v instanceof ExpandableView) {
             ExpandableView expandableView = (ExpandableView) v;
             ViewGroup transientContainer = expandableView.getTransientContainer();
             // If the child is animating away, it will still have a parent, so
@@ -4915,7 +4902,8 @@
     }
 
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+        IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
         StringBuilder sb = new StringBuilder("[")
                 .append(this.getClass().getSimpleName()).append(":")
                 .append(" pulsing=").append(mPulsing ? "T" : "f")
@@ -4929,15 +4917,15 @@
                 .append(" hideAmount=").append(mAmbientState.getHideAmount())
                 .append("]");
         pw.println(sb.toString());
-        DumpUtilsKt.withIndenting(pw, ipw -> {
+        DumpUtilsKt.withIncreasedIndent(pw, () -> {
             int childCount = getChildCount();
-            ipw.println("Number of children: " + childCount);
-            ipw.println();
+            pw.println("Number of children: " + childCount);
+            pw.println();
 
             for (int i = 0; i < childCount; i++) {
                 ExpandableView child = (ExpandableView) getChildAt(i);
-                child.dump(fd, ipw, args);
-                ipw.println();
+                child.dump(fd, pw, args);
+                pw.println();
             }
             int transientViewCount = getTransientViewCount();
             pw.println("Transient Views: " + transientViewCount);
@@ -6108,6 +6096,14 @@
         return mExpandHelperCallback;
     }
 
+    float getAppearFraction() {
+        return mLastSentAppear;
+    }
+
+    float getExpandedHeight() {
+        return mLastSentExpandedHeight;
+    }
+
     /** Enum for selecting some or all notification rows (does not included non-notif views). */
     @Retention(SOURCE)
     @IntDef({ROWS_ALL, ROWS_HIGH_PRIORITY, ROWS_GENTLE})
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 9492996..41a80c7 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
@@ -48,6 +48,7 @@
 import android.view.ViewGroup;
 import android.view.WindowInsets;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -67,7 +68,6 @@
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.media.KeyguardMediaController;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
@@ -85,6 +85,7 @@
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
 import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -98,6 +99,8 @@
 import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
+import com.android.systemui.statusbar.notification.collection.render.NotifStats;
 import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
 import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
 import com.android.systemui.statusbar.notification.dagger.SilentHeader;
@@ -159,7 +162,7 @@
     private final Resources mResources;
     private final NotificationSwipeHelper.Builder mNotificationSwipeHelperBuilder;
     private final ScrimController mScrimController;
-    private final FeatureFlags mFeatureFlags;
+    private final NotifPipelineFlags mNotifPipelineFlags;
     private final NotifPipeline mNotifPipeline;
     private final NotifCollection mNotifCollection;
     private final NotificationEntryManager mNotificationEntryManager;
@@ -192,6 +195,8 @@
 
     private final NotificationListContainerImpl mNotificationListContainer =
             new NotificationListContainerImpl();
+    private final NotifStackController mNotifStackController =
+            new NotifStackControllerImpl();
 
     @Nullable
     private NotificationActivityStarter mNotificationActivityStarter;
@@ -294,6 +299,8 @@
         }
     };
 
+    private NotifStats mNotifStats = NotifStats.getEmpty();
+
     private void updateResources() {
         mNotificationDragDownMovement = mResources.getDimensionPixelSize(
                 R.dimen.lockscreen_shade_notification_movement);
@@ -642,7 +649,7 @@
             NotificationGroupManagerLegacy legacyGroupManager,
             GroupExpansionManager groupManager,
             @SilentHeader SectionHeaderController silentHeaderController,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             NotifPipeline notifPipeline,
             NotifCollection notifCollection,
             NotificationEntryManager notificationEntryManager,
@@ -690,10 +697,10 @@
                 mStatusBar.requestNotificationUpdate("onGroupsChanged");
             }
         });
-        mLegacyGroupManager = featureFlags.isNewNotifPipelineRenderingEnabled()
+        mNotifPipelineFlags = notifPipelineFlags;
+        mLegacyGroupManager = mNotifPipelineFlags.isNewPipelineEnabled()
                 ? null : legacyGroupManager;
         mSilentHeaderController = silentHeaderController;
-        mFeatureFlags = featureFlags;
         mNotifPipeline = notifPipeline;
         mNotifCollection = notifCollection;
         mNotificationEntryManager = notificationEntryManager;
@@ -744,7 +751,7 @@
                 .setOnMenuEventListener(mMenuEventListener)
                 .build();
 
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             mNotifPipeline.addCollectionListener(new NotifCollectionListener() {
                 @Override
                 public void onEntryUpdated(NotificationEntry entry) {
@@ -866,6 +873,14 @@
         mView.setHeadsUpAppearanceController(controller);
     }
 
+    public float getAppearFraction() {
+        return mView.getAppearFraction();
+    }
+
+    public float getExpandedHeight() {
+        return mView.getExpandedHeight();
+    }
+
     public void requestLayout() {
         mView.requestLayout();
     }
@@ -988,7 +1003,7 @@
     }
 
     public int getVisibleNotificationCount() {
-        return mView.getVisibleNotificationCount();
+        return mNotifStats.getNumActiveNotifs();
     }
 
     public int getIntrinsicContentHeight() {
@@ -1183,7 +1198,7 @@
     public void updateShowEmptyShadeView() {
         mShowEmptyShadeView = mBarState != KEYGUARD
                 && (!mView.isQsExpanded() || mView.isUsingSplitNotificationShade())
-                && mView.getVisibleNotificationCount() == 0;
+                && getVisibleNotificationCount() == 0;
 
         mView.updateEmptyShadeView(
                 mShowEmptyShadeView,
@@ -1246,29 +1261,22 @@
     }
 
     public boolean hasNotifications(@SelectedRows int selection, boolean isClearable) {
-        if (mDynamicPrivacyController.isInLockedDownShade()) {
-            return false;
+        boolean hasAlertingMatchingClearable = isClearable
+                ? mNotifStats.getHasClearableAlertingNotifs()
+                : mNotifStats.getHasNonClearableAlertingNotifs();
+        boolean hasSilentMatchingClearable = isClearable
+                ? mNotifStats.getHasClearableSilentNotifs()
+                : mNotifStats.getHasNonClearableSilentNotifs();
+        switch (selection) {
+            case ROWS_GENTLE:
+                return hasSilentMatchingClearable;
+            case ROWS_HIGH_PRIORITY:
+                return hasAlertingMatchingClearable;
+            case ROWS_ALL:
+                return hasSilentMatchingClearable || hasAlertingMatchingClearable;
+            default:
+                throw new IllegalStateException("Bad selection: " + selection);
         }
-        int childCount = getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            View child = getChildAt(i);
-            if (!(child instanceof ExpandableNotificationRow)) {
-                continue;
-            }
-            final ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-            final boolean matchClearable =
-                    isClearable ? row.canViewBeDismissed() : !row.canViewBeDismissed();
-            final boolean inSection =
-                    NotificationStackScrollLayout.matchesSelection(row, selection);
-            if (matchClearable && inSection) {
-                if (mLegacyGroupManager == null
-                        || !mLegacyGroupManager.isSummaryOfSuppressedGroup(
-                        row.getEntry().getSbn())) {
-                    return true;
-                }
-            }
-        }
-        return false;
     }
 
     /**
@@ -1309,7 +1317,7 @@
     }
 
     public void updateSectionBoundaries(String reason) {
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             return;
         }
         mView.updateSectionBoundaries(reason);
@@ -1383,6 +1391,10 @@
         return mNotificationListContainer;
     }
 
+    public NotifStackController getNotifStackController() {
+        return mNotifStackController;
+    }
+
     public void resetCheckSnoozeLeavebehind() {
         mView.resetCheckSnoozeLeavebehind();
     }
@@ -1394,17 +1406,6 @@
                 mVisibilityProvider.obtain(entry, true));
     }
 
-    /**
-     * @return if the shade has currently any active notifications.
-     */
-    public boolean hasActiveNotifications() {
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
-            return !mNotifPipeline.getShadeList().isEmpty();
-        } else {
-            return mNotificationEntryManager.hasActiveNotifications();
-        }
-    }
-
     public void closeControlsIfOutsideTouch(MotionEvent ev) {
         NotificationGuts guts = mNotificationGutsManager.getExposedGuts();
         NotificationMenuRowPlugin menuRow = mSwipeHelper.getCurrentMenuRow();
@@ -1435,7 +1436,7 @@
 
     private void onAnimationEnd(List<ExpandableNotificationRow> viewsToRemove,
             @SelectedRows int selectedRows) {
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             if (selectedRows == ROWS_ALL) {
                 mNotifCollection.dismissAllNotifications(
                         mLockscreenUserManager.getCurrentUserId());
@@ -1876,4 +1877,13 @@
             }
         }
     }
+
+    private class NotifStackControllerImpl implements NotifStackController {
+        @Override
+        public void setNotifStats(@NonNull NotifStats notifStats) {
+            mNotifStats = notifStats;
+            updateFooter();
+            updateShowEmptyShadeView();
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
index eb7410c..1038e76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelper.java
@@ -468,8 +468,8 @@
         final int height = (view instanceof ExpandableView)
                 ? ((ExpandableView) view).getActualHeight()
                 : view.getHeight();
-        final int rx = (int) ev.getX();
-        final int ry = (int) ev.getY();
+        final int rx = (int) ev.getRawX();
+        final int ry = (int) ev.getRawY();
         int[] temp = new int[2];
         view.getLocationOnScreen(temp);
         final int x = temp[0];
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index 6d82a45..83bea84 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -29,6 +29,7 @@
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.statusbar.notification.AnimatableProperty;
+import com.android.systemui.statusbar.notification.NotificationFadeAware.FadeOptimizedNotification;
 import com.android.systemui.statusbar.notification.PropertyAnimator;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 import com.android.systemui.statusbar.policy.HeadsUpUtil;
@@ -206,14 +207,26 @@
         } else if (view.getAlpha() != this.alpha) {
             // apply layer type
             boolean becomesFullyVisible = this.alpha == 1.0f;
-            boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible
-                    && view.hasOverlappingRendering();
-            int layerType = view.getLayerType();
-            int newLayerType = newLayerTypeIsHardware
-                    ? View.LAYER_TYPE_HARDWARE
-                    : View.LAYER_TYPE_NONE;
-            if (layerType != newLayerType) {
-                view.setLayerType(newLayerType, null);
+            boolean becomesFaded = !becomesInvisible && !becomesFullyVisible;
+            if (FadeOptimizedNotification.FADE_LAYER_OPTIMIZATION_ENABLED
+                    && view instanceof FadeOptimizedNotification) {
+                // NOTE: A view that's going to utilize this interface to avoid having a hardware
+                //  layer will have to return false from hasOverlappingRendering(), so we
+                //  intentionally do not check that value in this if, even though we do in the else.
+                FadeOptimizedNotification fadeOptimizedView = (FadeOptimizedNotification) view;
+                boolean isFaded = fadeOptimizedView.isNotificationFaded();
+                if (isFaded != becomesFaded) {
+                    fadeOptimizedView.setNotificationFaded(becomesFaded);
+                }
+            } else {
+                boolean newLayerTypeIsHardware = becomesFaded && view.hasOverlappingRendering();
+                int layerType = view.getLayerType();
+                int newLayerType = newLayerTypeIsHardware
+                        ? View.LAYER_TYPE_HARDWARE
+                        : View.LAYER_TYPE_NONE;
+                if (layerType != newLayerType) {
+                    view.setLayerType(newLayerType, null);
+                }
             }
 
             // apply alpha
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index fa32620..244103c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -31,7 +31,7 @@
 import com.android.systemui.qs.AutoAddTracker;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.qs.ReduceBrightColorsController;
-import com.android.systemui.qs.SecureSetting;
+import com.android.systemui.qs.SettingObserver;
 import com.android.systemui.qs.external.CustomTile;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.CastController.CastDevice;
@@ -383,8 +383,8 @@
     };
 
     @VisibleForTesting
-    protected SecureSetting getSecureSettingForKey(String key) {
-        for (SecureSetting s : mAutoAddSettingList) {
+    protected SettingObserver getSecureSettingForKey(String key) {
+        for (SettingObserver s : mAutoAddSettingList) {
             if (Objects.equals(key, s.getKey())) {
                 return s;
             }
@@ -398,7 +398,7 @@
      * When the setting changes to a value different from 0, if the tile has not been auto added
      * before, it will be added and the listener will be stopped.
      */
-    private class AutoAddSetting extends SecureSetting {
+    private class AutoAddSetting extends SettingObserver {
         private final String mSpec;
 
         AutoAddSetting(
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 67f51cb..aa3b3e1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.hardware.biometrics.BiometricSourceType;
+import android.hardware.fingerprint.FingerprintManager;
 import android.metrics.LogMaker;
 import android.os.Handler;
 import android.os.PowerManager;
@@ -46,9 +47,11 @@
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 
 import java.io.FileDescriptor;
@@ -71,6 +74,7 @@
     private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
     private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
     private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl();
+    private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 3;
 
     @IntDef(prefix = { "MODE_" }, value = {
             MODE_NONE,
@@ -167,6 +171,10 @@
 
     private final MetricsLogger mMetricsLogger;
     private final AuthController mAuthController;
+    private final StatusBarStateController mStatusBarStateController;
+
+    private long mLastFpFailureUptimeMillis;
+    private int mNumConsecutiveFpFailures;
 
     private static final class PendingAuthenticated {
         public final int userId;
@@ -209,7 +217,10 @@
         BIOMETRIC_IRIS_FAILURE(403),
 
         @UiEvent(doc = "A biometric event of type iris errored.")
-        BIOMETRIC_IRIS_ERROR(404);
+        BIOMETRIC_IRIS_ERROR(404),
+
+        @UiEvent(doc = "Bouncer was shown as a result of consecutive failed UDFPS attempts.")
+        BIOMETRIC_BOUNCER_SHOWN(916);
 
         private final int mId;
 
@@ -257,7 +268,8 @@
             NotificationMediaManager notificationMediaManager,
             WakefulnessLifecycle wakefulnessLifecycle,
             ScreenLifecycle screenLifecycle,
-            AuthController authController) {
+            AuthController authController,
+            StatusBarStateController statusBarStateController) {
         mContext = context;
         mPowerManager = powerManager;
         mShadeController = shadeController;
@@ -279,6 +291,7 @@
         mKeyguardBypassController.setUnlockController(this);
         mMetricsLogger = metricsLogger;
         mAuthController = authController;
+        mStatusBarStateController = statusBarStateController;
         dumpManager.registerDumpable(getClass().getName(), this);
     }
 
@@ -620,6 +633,22 @@
                 .setType(MetricsEvent.TYPE_FAILURE).setSubtype(toSubtype(biometricSourceType)));
         Optional.ofNullable(BiometricUiEvent.FAILURE_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
                 .ifPresent(UI_EVENT_LOGGER::log);
+
+        long currUptimeMillis = SystemClock.uptimeMillis();
+        if (currUptimeMillis - mLastFpFailureUptimeMillis < 2000) { // attempt within 2 seconds
+            mNumConsecutiveFpFailures += 1;
+        } else {
+            mNumConsecutiveFpFailures = 1;
+        }
+        mLastFpFailureUptimeMillis = currUptimeMillis;
+
+        if (biometricSourceType.equals(BiometricSourceType.FINGERPRINT)
+                && mUpdateMonitor.isUdfpsSupported()
+                && mNumConsecutiveFpFailures >= FP_ATTEMPTS_BEFORE_SHOW_BOUNCER) {
+            mKeyguardViewController.showBouncer(true);
+            UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN);
+            mNumConsecutiveFpFailures = 0;
+        }
         cleanup();
     }
 
@@ -631,6 +660,16 @@
                 .addTaggedData(MetricsEvent.FIELD_BIOMETRIC_AUTH_ERROR, msgId));
         Optional.ofNullable(BiometricUiEvent.ERROR_EVENT_BY_SOURCE_TYPE.get(biometricSourceType))
                 .ifPresent(UI_EVENT_LOGGER::log);
+
+        // if we're on the shade and we're locked out, immediately show the bouncer
+        if (biometricSourceType == BiometricSourceType.FINGERPRINT
+                && (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT
+                || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT)
+                && mUpdateMonitor.isUdfpsSupported()
+                && (mStatusBarStateController.getState() == StatusBarState.SHADE
+                    || mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED)) {
+            mKeyguardViewController.showBouncer(true);
+        }
         cleanup();
     }
 
@@ -664,6 +703,8 @@
             mBiometricModeListener.onResetMode();
             mBiometricModeListener.notifyBiometricAuthModeChanged();
         }
+        mNumConsecutiveFpFailures = 0;
+        mLastFpFailureUptimeMillis = 0;
     }
 
     @VisibleForTesting
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 908cd34..ee51efb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DemoStatusIcons.java
@@ -30,6 +30,7 @@
 import com.android.systemui.R;
 import com.android.systemui.demomode.DemoMode;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
 import com.android.systemui.statusbar.StatusBarIconView;
@@ -255,7 +256,8 @@
     public void addMobileView(MobileIconState state) {
         Log.d(TAG, "addMobileView: ");
         StatusBarMobileView view = StatusBarMobileView.fromContext(
-                mContext, state.slot, mFeatureFlags.isCombinedStatusBarSignalIconsEnabled());
+                mContext, state.slot,
+                mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS));
 
         view.applyMobileState(state);
         view.setStaticDrawableColor(mColor);
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 49e3fe7..14f7134 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -35,6 +35,7 @@
 import com.android.systemui.doze.DozeScreenState;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.tuner.TunerService;
@@ -236,7 +237,7 @@
      */
     public boolean canControlUnlockedScreenOff() {
         return getAlwaysOn()
-                && mFeatureFlags.useNewLockscreenAnimations()
+                && mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)
                 && !getDisplayNeedsBlanking();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 927b4c8..8a7cf36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -24,6 +24,7 @@
 import com.android.internal.widget.ViewClippingUtil;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.RootView;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
@@ -35,23 +36,29 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentScope;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+import com.android.systemui.util.ViewController;
 
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 
+import javax.inject.Inject;
+
 /**
  * Controls the appearance of heads up notifications in the icon area and the header itself.
  */
-public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
-        DarkIconDispatcher.DarkReceiver, NotificationWakeUpCoordinator.WakeUpListener {
+@StatusBarFragmentScope
+public class HeadsUpAppearanceController extends ViewController<HeadsUpStatusBarView>
+        implements OnHeadsUpChangedListener,
+        DarkIconDispatcher.DarkReceiver,
+        NotificationWakeUpCoordinator.WakeUpListener {
     public static final int CONTENT_FADE_DURATION = 110;
     public static final int CONTENT_FADE_DELAY = 100;
     private final NotificationIconAreaController mNotificationIconAreaController;
     private final HeadsUpManagerPhone mHeadsUpManager;
     private final NotificationStackScrollLayoutController mStackScrollerController;
-    private final HeadsUpStatusBarView mHeadsUpStatusBarView;
     private final View mCenteredIconView;
     private final View mClockView;
     private final View mOperatorNameView;
@@ -67,8 +74,6 @@
     @VisibleForTesting
     float mExpandedHeight;
     @VisibleForTesting
-    boolean mIsExpanded;
-    @VisibleForTesting
     float mAppearFraction;
     private ExpandableNotificationRow mTrackedChild;
     private boolean mShown;
@@ -83,7 +88,7 @@
     Point mPoint;
     private KeyguardStateController mKeyguardStateController;
 
-
+    @Inject
     public HeadsUpAppearanceController(
             NotificationIconAreaController notificationIconAreaController,
             HeadsUpManagerPhone headsUpManager,
@@ -92,11 +97,15 @@
             KeyguardBypassController keyguardBypassController,
             KeyguardStateController keyguardStateController,
             NotificationWakeUpCoordinator wakeUpCoordinator, CommandQueue commandQueue,
-            NotificationPanelViewController notificationPanelViewController, View statusBarView) {
+            NotificationPanelViewController notificationPanelViewController,
+            @RootView PhoneStatusBarView statusBarView) {
         this(notificationIconAreaController, headsUpManager, statusBarStateController,
                 keyguardBypassController, wakeUpCoordinator, keyguardStateController,
                 commandQueue, notificationStackScrollLayoutController,
                 notificationPanelViewController,
+                // TODO(b/205609837): We should have the StatusBarFragmentComponent provide these
+                //  four views, and then we can delete this constructor and just use the one below
+                //  (which also removes the undesirable @VisibleForTesting).
                 statusBarView.findViewById(R.id.heads_up_status_bar_view),
                 statusBarView.findViewById(R.id.clock),
                 statusBarView.findViewById(R.id.operator_name_frame),
@@ -118,25 +127,27 @@
             View clockView,
             View operatorNameView,
             View centeredIconView) {
+        super(headsUpStatusBarView);
         mNotificationIconAreaController = notificationIconAreaController;
         mHeadsUpManager = headsUpManager;
-        mHeadsUpManager.addListener(this);
-        mHeadsUpStatusBarView = headsUpStatusBarView;
         mCenteredIconView = centeredIconView;
-        headsUpStatusBarView.setOnDrawingRectChangedListener(
-                () -> updateIsolatedIconLocation(true /* requireUpdate */));
+
+        // We may be mid-HUN-expansion when this controller is re-created (for example, if the user
+        // has started pulling down the notification shade from the HUN and then the font size
+        // changes). We need to re-fetch these values since they're used to correctly display the
+        // HUN during this shade expansion.
+        mTrackedChild = notificationPanelViewController.getTrackedHeadsUpNotification();
+        mAppearFraction = stackScrollerController.getAppearFraction();
+        mExpandedHeight = stackScrollerController.getExpandedHeight();
+
         mStackScrollerController = stackScrollerController;
         mNotificationPanelViewController = notificationPanelViewController;
-        notificationPanelViewController.addTrackingHeadsUpListener(mSetTrackingHeadsUp);
-        notificationPanelViewController.setHeadsUpAppearanceController(this);
-        mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight);
         mStackScrollerController.setHeadsUpAppearanceController(this);
         mClockView = clockView;
         mOperatorNameView = operatorNameView;
         mDarkIconDispatcher = Dependency.get(DarkIconDispatcher.class);
-        mDarkIconDispatcher.addDarkReceiver(this);
 
-        mHeadsUpStatusBarView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+        mView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
             @Override
             public void onLayoutChange(View v, int left, int top, int right, int bottom,
                     int oldLeft, int oldTop, int oldRight, int oldBottom) {
@@ -146,21 +157,32 @@
                     // trigger scroller to notify the latest panel translation
                     mStackScrollerController.requestLayout();
                 }
-                mHeadsUpStatusBarView.removeOnLayoutChangeListener(this);
+                mView.removeOnLayoutChangeListener(this);
             }
         });
         mBypassController = bypassController;
         mStatusBarStateController = stateController;
         mWakeUpCoordinator = wakeUpCoordinator;
-        wakeUpCoordinator.addListener(this);
         mCommandQueue = commandQueue;
         mKeyguardStateController = keyguardStateController;
     }
 
+    @Override
+    protected void onViewAttached() {
+        mHeadsUpManager.addListener(this);
+        mView.setOnDrawingRectChangedListener(
+                () -> updateIsolatedIconLocation(true /* requireUpdate */));
+        mWakeUpCoordinator.addListener(this);
+        mNotificationPanelViewController.addTrackingHeadsUpListener(mSetTrackingHeadsUp);
+        mNotificationPanelViewController.setHeadsUpAppearanceController(this);
+        mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight);
+        mDarkIconDispatcher.addDarkReceiver(this);
+    }
 
-    public void destroy() {
+    @Override
+    protected void onViewDetached() {
         mHeadsUpManager.removeListener(this);
-        mHeadsUpStatusBarView.setOnDrawingRectChangedListener(null);
+        mView.setOnDrawingRectChangedListener(null);
         mWakeUpCoordinator.removeListener(this);
         mNotificationPanelViewController.removeTrackingHeadsUpListener(mSetTrackingHeadsUp);
         mNotificationPanelViewController.setHeadsUpAppearanceController(null);
@@ -170,7 +192,7 @@
 
     private void updateIsolatedIconLocation(boolean requireStateUpdate) {
         mNotificationIconAreaController.setIsolatedIconLocation(
-                mHeadsUpStatusBarView.getIconDrawingRect(), requireStateUpdate);
+                mView.getIconDrawingRect(), requireStateUpdate);
     }
 
     @Override
@@ -184,20 +206,20 @@
         if (shouldBeVisible()) {
             newEntry = mHeadsUpManager.getTopEntry();
         }
-        NotificationEntry previousEntry = mHeadsUpStatusBarView.getShowingEntry();
-        mHeadsUpStatusBarView.setEntry(newEntry);
+        NotificationEntry previousEntry = mView.getShowingEntry();
+        mView.setEntry(newEntry);
         if (newEntry != previousEntry) {
             boolean animateIsolation = false;
             if (newEntry == null) {
                 // no heads up anymore, lets start the disappear animation
 
                 setShown(false);
-                animateIsolation = !mIsExpanded;
+                animateIsolation = !isExpanded();
             } else if (previousEntry == null) {
                 // We now have a headsUp and didn't have one before. Let's start the disappear
                 // animation
                 setShown(true);
-                animateIsolation = !mIsExpanded;
+                animateIsolation = !isExpanded();
             }
             updateIsolatedIconLocation(false /* requireUpdate */);
             mNotificationIconAreaController.showIconIsolated(newEntry == null ? null
@@ -210,8 +232,8 @@
             mShown = isShown;
             if (isShown) {
                 updateParentClipping(false /* shouldClip */);
-                mHeadsUpStatusBarView.setVisibility(View.VISIBLE);
-                show(mHeadsUpStatusBarView);
+                mView.setVisibility(View.VISIBLE);
+                show(mView);
                 hide(mClockView, View.INVISIBLE);
                 if (mCenteredIconView.getVisibility() != View.GONE) {
                     hide(mCenteredIconView, View.INVISIBLE);
@@ -227,21 +249,21 @@
                 if (mOperatorNameView != null) {
                     show(mOperatorNameView);
                 }
-                hide(mHeadsUpStatusBarView, View.GONE, () -> {
+                hide(mView, View.GONE, () -> {
                     updateParentClipping(true /* shouldClip */);
                 });
             }
             // Show the status bar icons when the view gets shown / hidden
             if (mStatusBarStateController.getState() != StatusBarState.SHADE) {
                 mCommandQueue.recomputeDisableFlags(
-                        mHeadsUpStatusBarView.getContext().getDisplayId(), false);
+                        mView.getContext().getDisplayId(), false);
             }
         }
     }
 
     private void updateParentClipping(boolean shouldClip) {
         ViewClippingUtil.setClippingDeactivated(
-                mHeadsUpStatusBarView, !shouldClip, mParentClippingParams);
+                mView, !shouldClip, mParentClippingParams);
     }
 
     /**
@@ -310,7 +332,7 @@
      */
     public boolean shouldBeVisible() {
         boolean notificationsShown = !mWakeUpCoordinator.getNotificationsFullyHidden();
-        boolean canShow = !mIsExpanded && notificationsShown;
+        boolean canShow = !isExpanded() && notificationsShown;
         if (mBypassController.getBypassEnabled() &&
                 (mStatusBarStateController.getState() == StatusBarState.KEYGUARD
                         || mKeyguardStateController.isKeyguardGoingAway())
@@ -328,17 +350,17 @@
 
     public void setAppearFraction(float expandedHeight, float appearFraction) {
         boolean changed = expandedHeight != mExpandedHeight;
+        boolean oldIsExpanded = isExpanded();
+
         mExpandedHeight = expandedHeight;
         mAppearFraction = appearFraction;
-        boolean isExpanded = expandedHeight > 0;
         // We only notify if the expandedHeight changed and not on the appearFraction, since
         // otherwise we may run into an infinite loop where the panel and this are constantly
         // updating themselves over just a small fraction
         if (changed) {
             updateHeadsUpHeaders();
         }
-        if (isExpanded != mIsExpanded) {
-            mIsExpanded = isExpanded;
+        if (isExpanded() != oldIsExpanded) {
             updateTopEntry();
         }
     }
@@ -358,6 +380,10 @@
         }
     }
 
+    private boolean isExpanded() {
+        return mExpandedHeight > 0;
+    }
+
     private void updateHeadsUpHeaders() {
         mHeadsUpManager.getAllEntries().forEach(entry -> {
             updateHeader(entry);
@@ -376,22 +402,13 @@
 
     @Override
     public void onDarkChanged(Rect area, float darkIntensity, int tint) {
-        mHeadsUpStatusBarView.onDarkChanged(area, darkIntensity, tint);
+        mView.onDarkChanged(area, darkIntensity, tint);
     }
 
     public void onStateChanged() {
         updateTopEntry();
     }
 
-    void readFrom(HeadsUpAppearanceController oldController) {
-        if (oldController != null) {
-            mTrackedChild = oldController.mTrackedChild;
-            mExpandedHeight = oldController.mExpandedHeight;
-            mIsExpanded = oldController.mIsExpanded;
-            mAppearFraction = oldController.mAppearFraction;
-        }
-    }
-
     @Override
     public void onFullyHiddenChanged(boolean isFullyHidden) {
         updateTopEntry();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index 407d287..622c45e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -72,6 +72,7 @@
 import android.widget.TextView;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.widget.LockPatternUtils;
@@ -154,6 +155,7 @@
     private ControlsComponent mControlsComponent;
     private boolean mControlServicesAvailable = false;
 
+    @Nullable private View mAmbientIndicationArea;
     private ViewGroup mIndicationArea;
     private TextView mIndicationText;
     private TextView mIndicationTextBottom;
@@ -274,6 +276,29 @@
 
     public void initFrom(KeyguardBottomAreaView oldBottomArea) {
         setStatusBar(oldBottomArea.mStatusBar);
+
+        // if it exists, continue to use the original ambient indication container
+        // instead of the newly inflated one
+        if (mAmbientIndicationArea != null) {
+            // remove old ambient indication from its parent
+            View originalAmbientIndicationView =
+                    oldBottomArea.findViewById(R.id.ambient_indication_container);
+            ((ViewGroup) originalAmbientIndicationView.getParent())
+                    .removeView(originalAmbientIndicationView);
+
+            // remove current ambient indication from its parent (discard)
+            ViewGroup ambientIndicationParent = (ViewGroup) mAmbientIndicationArea.getParent();
+            int ambientIndicationIndex =
+                    ambientIndicationParent.indexOfChild(mAmbientIndicationArea);
+            ambientIndicationParent.removeView(mAmbientIndicationArea);
+
+            // add the old ambient indication to this view
+            ambientIndicationParent.addView(originalAmbientIndicationView, ambientIndicationIndex);
+            mAmbientIndicationArea = originalAmbientIndicationView;
+
+            // update burn-in offsets
+            dozeTimeTick();
+        }
     }
 
     @Override
@@ -288,6 +313,7 @@
         mQRCodeScannerButton = findViewById(R.id.qr_code_scanner_button);
         mControlsButton = findViewById(R.id.controls_button);
         mIndicationArea = findViewById(R.id.keyguard_indication_area);
+        mAmbientIndicationArea = findViewById(R.id.ambient_indication_container);
         mIndicationText = findViewById(R.id.keyguard_indication_text);
         mIndicationTextBottom = findViewById(R.id.keyguard_indication_text_bottom);
         mIndicationBottomMargin = getResources().getDimensionPixelSize(
@@ -923,6 +949,7 @@
         int burnInYOffset = getBurnInOffset(mBurnInYOffset * 2, false /* xAxis */)
                 - mBurnInYOffset;
         mIndicationArea.setTranslationY(burnInYOffset * mDarkAmount);
+        mAmbientIndicationArea.setTranslationY(burnInYOffset * mDarkAmount);
     }
 
     public void setAntiBurnInOffsetX(int burnInXOffset) {
@@ -931,6 +958,7 @@
         }
         mBurnInXOffset = burnInXOffset;
         mIndicationArea.setTranslationX(burnInXOffset);
+        mAmbientIndicationArea.setTranslationX(burnInXOffset);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 353868b..9647486 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -21,6 +21,7 @@
 
 import android.content.Context;
 import android.content.res.ColorStateList;
+import android.hardware.biometrics.BiometricSourceType;
 import android.os.Handler;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -81,6 +82,13 @@
                 public void onStrongAuthStateChanged(int userId) {
                     mBouncerPromptReason = mCallback.getBouncerPromptReason();
                 }
+
+                @Override
+                public void onLockedOutStateChanged(BiometricSourceType type) {
+                    if (type == BiometricSourceType.FINGERPRINT) {
+                        mBouncerPromptReason = mCallback.getBouncerPromptReason();
+                    }
+                }
             };
     private final Runnable mRemoveViewRunnable = this::removeView;
     private final KeyguardBypassController mKeyguardBypassController;
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 570b0ca..88ae0db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -37,7 +37,6 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.DarkIconDispatcher;
-import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.policy.BatteryController;
 
 import java.io.FileDescriptor;
@@ -251,7 +250,7 @@
 
     private void updateNavigation() {
         if (mNavigationBarController != null
-                && !QuickStepContract.isGesturalMode(mNavigationMode)) {
+                && mNavigationBarController.supportsIconTintForNavMode(mNavigationMode)) {
             mNavigationBarController.setIconsDark(mNavigationLight, animateChange());
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 9021b74..415fb92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -28,6 +28,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.animation.Interpolators;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CommandQueue.Callbacks;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -230,6 +231,14 @@
     }
 
     /**
+     * Return whether to use the tint calculated in this class for nav icons.
+     */
+    public boolean supportsIconTintForNavMode(int navigationMode) {
+        // In gesture mode, we already do region sampling to update tint based on content beneath.
+        return !QuickStepContract.isGesturalMode(navigationMode);
+    }
+
+    /**
      * Interface to apply a specific dark intensity.
      */
     public interface DarkIntensityApplier {
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 3f33281..68ab077 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightsOutNotifController.java
@@ -124,6 +124,9 @@
                         public void onAnimationEnd(Animator a) {
                             mLightsOutNotifView.setAlpha(showDot ? 1 : 0);
                             mLightsOutNotifView.setVisibility(showDot ? View.VISIBLE : View.GONE);
+                            // Unset the listener, otherwise this may persist for
+                            // another view property animation
+                            mLightsOutNotifView.animate().setListener(null);
                         }
                     })
                     .start();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java
index d69b31f..eb5db29 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitchController.java
@@ -24,6 +24,7 @@
 
 import com.android.systemui.R;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.qs.FooterActionsView;
@@ -53,7 +54,7 @@
                 return;
             }
 
-            if (mFeatureFlags.useNewUserSwitcher()) {
+            if (mFeatureFlags.isEnabled(Flags.NEW_USER_SWITCHER)) {
                 mUserSwitchDialogController.showDialog(v);
             } else {
                 View center = mView.getChildCount() > 0 ? mView.getChildAt(0) : mView;
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 a66af04..8931874 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -126,6 +126,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.doze.DozeLog;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
 import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.idle.IdleHostView;
@@ -183,6 +184,7 @@
 import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
 import com.android.systemui.statusbar.phone.LockscreenGestureLogger.LockscreenUiEvent;
 import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
 import com.android.systemui.statusbar.phone.panelstate.PanelState;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -478,9 +480,13 @@
     private boolean mUserSetupComplete;
     private boolean mHideIconsDuringLaunchAnimation = true;
     private int mStackScrollerMeasuringPass;
-    private ArrayList<Consumer<ExpandableNotificationRow>>
-            mTrackingHeadsUpListeners =
-            new ArrayList<>();
+    /**
+     * Non-null if there's a heads-up notification that we're currently tracking the position of.
+     */
+    @Nullable
+    private ExpandableNotificationRow mTrackedHeadsUpNotification;
+    private final ArrayList<Consumer<ExpandableNotificationRow>>
+            mTrackingHeadsUpListeners = new ArrayList<>();
     private HeadsUpAppearanceController mHeadsUpAppearanceController;
 
     private int mPanelAlpha;
@@ -504,23 +510,11 @@
                     mPanelAlphaAnimator.getProperty(), Interpolators.ALPHA_IN);
     private final NotificationEntryManager mEntryManager;
 
-    private final CommunalSourceMonitor.Callback mCommunalSourceMonitorCallback =
-            new CommunalSourceMonitor.Callback() {
-                @Override
-                public void onSourceAvailable(WeakReference<CommunalSource> source) {
-                    setCommunalSource(source);
-                }
-            };
+    private final CommunalSourceMonitor.Callback mCommunalSourceMonitorCallback;
 
     private WeakReference<CommunalSource> mCommunalSource;
 
-    private final CommunalSource.Callback mCommunalSourceCallback =
-            new CommunalSource.Callback() {
-                @Override
-                public void onDisconnected() {
-                    setCommunalSource(null /*source*/);
-                }
-            };
+    private final CommunalSource.Callback mCommunalSourceCallback;
 
     private final CommandQueue mCommandQueue;
     private final NotificationLockscreenUserManager mLockscreenUserManager;
@@ -902,6 +896,15 @@
 
         mMaxKeyguardNotifications = resources.getInteger(R.integer.keyguard_max_notification_count);
         mKeyguardUnfoldTransition = unfoldComponent.map(c -> c.getKeyguardUnfoldTransition());
+
+        mCommunalSourceCallback = () -> {
+            mUiExecutor.execute(() -> setCommunalSource(null /*source*/));
+        };
+
+        mCommunalSourceMonitorCallback = (source) -> {
+            mUiExecutor.execute(() -> setCommunalSource(source));
+        };
+
         updateUserSwitcherFlags();
         onFinishInflate();
     }
@@ -3019,6 +3022,10 @@
             mStatusBarTouchableRegionManager.setPanelExpanded(isExpanded);
             mStatusBar.setPanelExpanded(isExpanded);
             mPanelExpanded = isExpanded;
+
+            if (!isExpanded && mQs != null && mQs.isCustomizing()) {
+                mQs.closeCustomizer();
+            }
         }
     }
 
@@ -3195,18 +3202,24 @@
         mQsExpandImmediate = false;
         mNotificationStackScrollLayoutController.setShouldShowShelfOnly(false);
         mTwoFingerQsExpandPossible = false;
-        notifyListenersTrackingHeadsUp(null);
+        updateTrackingHeadsUp(null);
         mExpandingFromHeadsUp = false;
         setPanelScrimMinFraction(0.0f);
     }
 
-    private void notifyListenersTrackingHeadsUp(ExpandableNotificationRow pickedChild) {
+    private void updateTrackingHeadsUp(@Nullable ExpandableNotificationRow pickedChild) {
+        mTrackedHeadsUpNotification = pickedChild;
         for (int i = 0; i < mTrackingHeadsUpListeners.size(); i++) {
             Consumer<ExpandableNotificationRow> listener = mTrackingHeadsUpListeners.get(i);
             listener.accept(pickedChild);
         }
     }
 
+    @Nullable
+    public ExpandableNotificationRow getTrackedHeadsUpNotification() {
+        return mTrackedHeadsUpNotification;
+    }
+
     private void setListening(boolean listening) {
         mKeyguardStatusBarViewController.setBatteryListening(listening);
         if (mQs == null) return;
@@ -3317,10 +3330,20 @@
         return mQs.isShowingDetail();
     }
 
+    /** Returns whether the QS customizer is currently active. */
+    public boolean isQsCustomizing() {
+        return mQs.isCustomizing();
+    }
+
     public void closeQsDetail() {
         mQs.closeDetail();
     }
 
+    /** Close the QS customizer if it is open. */
+    public void closeQsCustomizer() {
+        mQs.closeCustomizer();
+    }
+
     public boolean isLaunchTransitionFinished() {
         return mIsLaunchTransitionFinished;
     }
@@ -3433,7 +3456,7 @@
 
     public void setTrackedHeadsUp(ExpandableNotificationRow pickedChild) {
         if (pickedChild != null) {
-            notifyListenersTrackingHeadsUp(pickedChild);
+            updateTrackingHeadsUp(pickedChild);
             mExpandingFromHeadsUp = true;
         }
         // otherwise we update the state when the expansion is finished
@@ -4144,7 +4167,7 @@
                 com.android.internal.R.bool.config_keyguardUserSwitcher);
         mKeyguardQsUserSwitchEnabled =
                 mKeyguardUserSwitcherEnabled
-                        && mFeatureFlags.isKeyguardQsUserDetailsShortcutEnabled();
+                        && mFeatureFlags.isEnabled(Flags.QS_USER_DETAIL_SHORTCUT);
     }
 
     private void registerSettingsChangeListener() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
index 9cefded..bf54677 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsButton.java
@@ -120,6 +120,9 @@
                         setAlpha(1f);
                         setTranslationX(0);
                         cancelLongClick();
+                        // Unset the listener, otherwise this may persist for
+                        // another view property animation
+                        animate().setListener(null);
                     }
 
                     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
index c814622..fc549e2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
@@ -23,8 +23,10 @@
 import com.android.systemui.battery.BatteryMeterView
 import com.android.systemui.battery.BatteryMeterViewController
 import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.qs.carrier.QSCarrierGroupController
 import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
+import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_BATTERY_CONTROLLER
 import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.SPLIT_SHADE_HEADER
 import javax.inject.Inject
 import javax.inject.Named
@@ -35,7 +37,7 @@
     private val statusBarIconController: StatusBarIconController,
     qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder,
     featureFlags: FeatureFlags,
-    batteryMeterViewController: BatteryMeterViewController
+    @Named(SPLIT_SHADE_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController
 ) {
 
     companion object {
@@ -43,7 +45,7 @@
         private val SPLIT_HEADER_TRANSITION_ID = R.id.split_header_transition
     }
 
-    private val combinedHeaders = featureFlags.useCombinedQSHeaders()
+    private val combinedHeaders = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)
     // TODO(b/194178072) Handle RSSI hiding when multi carrier
     private val iconManager: StatusBarIconController.IconManager
     private val qsCarrierGroupController: QSCarrierGroupController
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 b47e71a..84ef079 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -40,7 +40,6 @@
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.TransitionMode;
-import static com.android.wm.shell.bubbles.BubbleController.TASKBAR_CHANGED_BROADCAST;
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -91,6 +90,7 @@
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.Slog;
@@ -134,10 +134,10 @@
 import com.android.systemui.InitController;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
+import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.animation.DelegateLaunchAnimatorController;
 import com.android.systemui.assist.AssistManager;
-import com.android.systemui.battery.BatteryMeterViewController;
 import com.android.systemui.biometrics.AuthRippleController;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.camera.CameraIntents;
@@ -150,8 +150,10 @@
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.emergency.EmergencyGesture;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.fragments.ExtensionFragmentListener;
 import com.android.systemui.fragments.FragmentHostManager;
+import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.KeyguardService;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -200,6 +202,7 @@
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
@@ -217,6 +220,9 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
 import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -504,6 +510,7 @@
     private final NotificationsController mNotificationsController;
     private final OngoingCallController mOngoingCallController;
     private final SystemStatusAnimationScheduler mAnimationScheduler;
+    private final StatusBarSignalPolicy mStatusBarSignalPolicy;
     private final StatusBarLocationPublisher mStatusBarLocationPublisher;
     private final StatusBarIconController mStatusBarIconController;
     private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
@@ -516,7 +523,6 @@
     private QSPanelController mQSPanelController;
 
     private final OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
-    private final PhoneStatusBarViewController.Factory mPhoneStatusBarViewControllerFactory;
     KeyguardIndicationController mKeyguardIndicationController;
 
     private View mReportRejectedTouch;
@@ -535,7 +541,7 @@
     protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
     private final BrightnessSliderController.Factory mBrightnessSliderFactory;
     private final FeatureFlags mFeatureFlags;
-
+    private final FragmentService mFragmentService;
     private final WallpaperController mWallpaperController;
     private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
     private final MessageRouter mMessageRouter;
@@ -543,6 +549,8 @@
     private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
     private final TunerService mTunerService;
 
+    private StatusBarComponent mStatusBarComponent;
+
     // Flags for disabling the status bar
     // Two variables becaseu the first one evidently ran out of room for new flags.
     private int mDisabled1 = 0;
@@ -659,7 +667,6 @@
     private boolean mNoAnimationOnNextBarModeChange;
     private final SysuiStatusBarStateController mStatusBarStateController;
 
-    private HeadsUpAppearanceController mHeadsUpAppearanceController;
     private final ActivityLaunchAnimator mActivityLaunchAnimator;
     private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
     protected StatusBarNotificationPresenter mPresenter;
@@ -669,10 +676,10 @@
     private final Optional<Bubbles> mBubblesOptional;
     private final Bubbles.BubbleExpandListener mBubbleExpandListener;
     private final Optional<StartingSurface> mStartingSurfaceOptional;
+    private final NotifPipelineFlags mNotifPipelineFlags;
 
     private final ActivityIntentHelper mActivityIntentHelper;
     private NotificationStackScrollLayoutController mStackScrollerController;
-    private BatteryMeterViewController mBatteryMeterViewController;
 
     private final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener =
             (extractor, which) -> updateTheme();
@@ -688,10 +695,12 @@
     public StatusBar(
             Context context,
             NotificationsController notificationsController,
+            FragmentService fragmentService,
             LightBarController lightBarController,
             AutoHideController autoHideController,
             StatusBarWindowController statusBarWindowController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
+            StatusBarSignalPolicy statusBarSignalPolicy,
             PulseExpansionHandler pulseExpansionHandler,
             NotificationWakeUpCoordinator notificationWakeUpCoordinator,
             KeyguardBypassController keyguardBypassController,
@@ -728,6 +737,7 @@
             VisualStabilityManager visualStabilityManager,
             DeviceProvisionedController deviceProvisionedController,
             NavigationBarController navigationBarController,
+            AccessibilityFloatingMenuController accessibilityFloatingMenuController,
             Lazy<AssistManager> assistManagerLazy,
             ConfigurationController configurationController,
             NotificationShadeWindowController notificationShadeWindowController,
@@ -759,7 +769,6 @@
             ExtensionController extensionController,
             UserInfoControllerImpl userInfoControllerImpl,
             OperatorNameViewController.Factory operatorNameViewControllerFactory,
-            PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory,
             PhoneStatusBarPolicy phoneStatusBarPolicy,
             KeyguardIndicationController keyguardIndicationController,
             DemoModeController demoModeController,
@@ -784,9 +793,11 @@
             Optional<StartingSurface> startingSurfaceOptional,
             TunerService tunerService,
             DumpManager dumpManager,
-            ActivityLaunchAnimator activityLaunchAnimator) {
+            ActivityLaunchAnimator activityLaunchAnimator,
+            NotifPipelineFlags notifPipelineFlags) {
         super(context);
         mNotificationsController = notificationsController;
+        mFragmentService = fragmentService;
         mLightBarController = lightBarController;
         mAutoHideController = autoHideController;
         mStatusBarWindowController = statusBarWindowController;
@@ -797,7 +808,6 @@
         mKeyguardStateController = keyguardStateController;
         mHeadsUpManager = headsUpManagerPhone;
         mOperatorNameViewControllerFactory = operatorNameViewControllerFactory;
-        mPhoneStatusBarViewControllerFactory = phoneStatusBarViewControllerFactory;
         mKeyguardIndicationController = keyguardIndicationController;
         mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
         mDynamicPrivacyController = dynamicPrivacyController;
@@ -831,6 +841,7 @@
         mVisualStabilityManager = visualStabilityManager;
         mDeviceProvisionedController = deviceProvisionedController;
         mNavigationBarController = navigationBarController;
+        mAccessibilityFloatingMenuController = accessibilityFloatingMenuController;
         mAssistManagerLazy = assistManagerLazy;
         mConfigurationController = configurationController;
         mNotificationShadeWindowController = notificationShadeWindowController;
@@ -867,6 +878,7 @@
         mWallpaperController = wallpaperController;
         mOngoingCallController = ongoingCallController;
         mAnimationScheduler = animationScheduler;
+        mStatusBarSignalPolicy = statusBarSignalPolicy;
         mStatusBarLocationPublisher = locationPublisher;
         mStatusBarIconController = statusBarIconController;
         mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
@@ -881,6 +893,7 @@
 
         mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
         mStartingSurfaceOptional = startingSurfaceOptional;
+        mNotifPipelineFlags = notifPipelineFlags;
         lockscreenShadeTransitionController.setStatusbar(this);
 
         mPanelExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged);
@@ -918,10 +931,9 @@
         mBypassHeadsUpNotifier.setUp();
         if (mBubblesOptional.isPresent()) {
             mBubblesOptional.get().setExpandListener(mBubbleExpandListener);
-            IntentFilter filter = new IntentFilter(TASKBAR_CHANGED_BROADCAST);
-            mBroadcastDispatcher.registerReceiver(mTaskbarChangeReceiver, filter);
         }
 
+        mStatusBarSignalPolicy.init();
         mKeyguardIndicationController.init();
 
         mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
@@ -1045,6 +1057,8 @@
         mBatteryController.observe(mLifecycle, mBatteryStateChangeCallback);
         mLifecycle.setCurrentState(RESUMED);
 
+        mAccessibilityFloatingMenuController.init();
+
         // set the initial view visibility
         int disabledFlags1 = result.mDisabledFlags1;
         int disabledFlags2 = result.mDisabledFlags2;
@@ -1134,27 +1148,16 @@
         mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class);
         mStatusBarWindowController.getFragmentHostManager()
                 .addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
-                    CollapsedStatusBarFragment statusBarFragment =
-                            (CollapsedStatusBarFragment) fragment;
+                    StatusBarFragmentComponent statusBarFragmentComponent =
+                            ((CollapsedStatusBarFragment) fragment).getStatusBarFragmentComponent();
+                    if (statusBarFragmentComponent == null) {
+                        throw new IllegalStateException(
+                                "CollapsedStatusBarFragment should have a valid component");
+                    }
 
-                    PhoneStatusBarView oldStatusBarView = mStatusBarView;
-                    mStatusBarView = (PhoneStatusBarView) statusBarFragment.getView();
-
-                    mPhoneStatusBarViewController = mPhoneStatusBarViewControllerFactory
-                            .create(mStatusBarView, mNotificationPanelViewController
-                                    .getStatusBarTouchEventHandler());
-                    mPhoneStatusBarViewController.init();
-
-                    mBatteryMeterViewController = new BatteryMeterViewController(
-                            mStatusBarView.findViewById(R.id.battery),
-                            mConfigurationController,
-                            mTunerService,
-                            mBroadcastDispatcher,
-                            mMainHandler,
-                            mContext.getContentResolver(),
-                            mBatteryController
-                    );
-                    mBatteryMeterViewController.init();
+                    mStatusBarView = statusBarFragmentComponent.getPhoneStatusBarView();
+                    mPhoneStatusBarViewController =
+                            statusBarFragmentComponent.getPhoneStatusBarViewController();
 
                     // Ensure we re-propagate panel expansion values to the panel controller and
                     // any listeners it may have, such as PanelBar. This will also ensure we
@@ -1164,21 +1167,6 @@
                     mNotificationPanelViewController.updatePanelExpansionAndVisibility();
                     setBouncerShowingForStatusBarComponents(mBouncerShowing);
 
-                    HeadsUpAppearanceController oldController = mHeadsUpAppearanceController;
-                    if (mHeadsUpAppearanceController != null) {
-                        // This view is being recreated, let's destroy the old one
-                        mHeadsUpAppearanceController.destroy();
-                    }
-                    // TODO: this should probably be scoped to the StatusBarComponent
-                    // TODO (b/136993073) Separate notification shade and status bar
-                    mHeadsUpAppearanceController = new HeadsUpAppearanceController(
-                            mNotificationIconAreaController, mHeadsUpManager,
-                            mStackScrollerController,
-                            mStatusBarStateController, mKeyguardBypassController,
-                            mKeyguardStateController, mWakeUpCoordinator, mCommandQueue,
-                            mNotificationPanelViewController, mStatusBarView);
-                    mHeadsUpAppearanceController.readFrom(oldController);
-
                     mLightsOutNotifController.setLightsOutNotifView(
                             mStatusBarView.findViewById(R.id.notification_lights_out));
                     mNotificationShadeWindowViewController.setStatusBarView(mStatusBarView);
@@ -1186,23 +1174,7 @@
                 }).getFragmentManager()
                 .beginTransaction()
                 .replace(R.id.status_bar_container,
-                        new CollapsedStatusBarFragment(
-                                mOngoingCallController,
-                                mAnimationScheduler,
-                                mStatusBarLocationPublisher,
-                                mNotificationIconAreaController,
-                                mPanelExpansionStateManager,
-                                mFeatureFlags,
-                                mStatusBarIconController,
-                                mStatusBarHideIconsForBouncerManager,
-                                mKeyguardStateController,
-                                mNetworkController,
-                                mStatusBarStateController,
-                                () -> Optional.of(this),
-                                mCommandQueue,
-                                mCollapsedStatusBarFragmentLogger,
-                                mOperatorNameViewControllerFactory
-                        ),
+                        mStatusBarComponent.createCollapsedStatusBarFragment(),
                         CollapsedStatusBarFragment.TAG)
                 .commit();
 
@@ -1461,7 +1433,6 @@
                 mDynamicPrivacyController,
                 mKeyguardStateController,
                 mKeyguardIndicationController,
-                mFeatureFlags,
                 this /* statusBar */,
                 mShadeController,
                 mLockscreenShadeTransitionController,
@@ -1478,7 +1449,8 @@
                 mInitController,
                 mNotificationInterruptStateProvider,
                 mRemoteInputManager,
-                mConfigurationController);
+                mConfigurationController,
+                mNotifPipelineFlags);
 
         mNotificationShelfController.setOnActivatedListener(mPresenter);
         mRemoteInputManager.addControllerCallback(mNotificationShadeWindowController);
@@ -1499,6 +1471,7 @@
                 mBubblesOptional,
                 mPresenter,
                 mStackScrollerController.getNotificationListContainer(),
+                mStackScrollerController.getNotifStackController(),
                 mNotificationActivityStarter,
                 mPresenter);
     }
@@ -1558,32 +1531,34 @@
     }
 
     private void inflateStatusBarWindow() {
-        StatusBarComponent statusBarComponent = mStatusBarComponentFactory.create();
-        mNotificationShadeWindowView = statusBarComponent.getNotificationShadeWindowView();
-        mNotificationShadeWindowViewController = statusBarComponent
+        mStatusBarComponent = mStatusBarComponentFactory.create();
+        mFragmentService.addFragmentInstantiationProvider(mStatusBarComponent);
+
+        mNotificationShadeWindowView = mStatusBarComponent.getNotificationShadeWindowView();
+        mNotificationShadeWindowViewController = mStatusBarComponent
                 .getNotificationShadeWindowViewController();
         mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
         mNotificationShadeWindowViewController.setupExpandedStatusBar();
-        mNotificationPanelViewController = statusBarComponent.getNotificationPanelViewController();
-        statusBarComponent.getLockIconViewController().init();
-        mStackScrollerController = statusBarComponent.getNotificationStackScrollLayoutController();
+        mNotificationPanelViewController = mStatusBarComponent.getNotificationPanelViewController();
+        mStatusBarComponent.getLockIconViewController().init();
+        mStackScrollerController = mStatusBarComponent.getNotificationStackScrollLayoutController();
         mStackScroller = mStackScrollerController.getView();
 
-        mNotificationShelfController = statusBarComponent.getNotificationShelfController();
-        mAuthRippleController = statusBarComponent.getAuthRippleController();
+        mNotificationShelfController = mStatusBarComponent.getNotificationShelfController();
+        mAuthRippleController = mStatusBarComponent.getAuthRippleController();
         mAuthRippleController.init();
 
-        mHeadsUpManager.addListener(statusBarComponent.getStatusBarHeadsUpChangeListener());
+        mHeadsUpManager.addListener(mStatusBarComponent.getStatusBarHeadsUpChangeListener());
 
-        mHeadsUpManager.addListener(statusBarComponent.getStatusBarHeadsUpChangeListener());
+        mHeadsUpManager.addListener(mStatusBarComponent.getStatusBarHeadsUpChangeListener());
 
         // Listen for demo mode changes
-        mDemoModeController.addCallback(statusBarComponent.getStatusBarDemoMode());
+        mDemoModeController.addCallback(mStatusBarComponent.getStatusBarDemoMode());
 
         if (mCommandQueueCallbacks != null) {
             mCommandQueue.removeCallback(mCommandQueueCallbacks);
         }
-        mCommandQueueCallbacks = statusBarComponent.getStatusBarCommandQueueCallbacks();
+        mCommandQueueCallbacks = mStatusBarComponent.getStatusBarCommandQueueCallbacks();
         // Connect in to the status bar manager service
         mCommandQueue.addCallback(mCommandQueueCallbacks);
     }
@@ -1918,10 +1893,6 @@
         mScrimController.setKeyguardOccluded(occluded);
     }
 
-    public boolean headsUpShouldBeVisible() {
-        return mHeadsUpAppearanceController.shouldBeVisible();
-    }
-
     /** A launch animation was cancelled. */
     //TODO: These can / should probably be moved to NotificationPresenter or ShadeController
     public void onLaunchAnimationCancelled(boolean isLaunchForActivity) {
@@ -2001,7 +1972,7 @@
         }
     }
 
-    public void maybeEscalateHeadsUp() {
+    private void maybeEscalateHeadsUp() {
         mHeadsUpManager.getAllEntries().forEach(entry -> {
             final StatusBarNotification sbn = entry.getSbn();
             final Notification notification = sbn.getNotification();
@@ -2012,6 +1983,7 @@
                 try {
                     EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION,
                             sbn.getKey());
+                    wakeUpForFullScreenIntent();
                     notification.fullScreenIntent.send();
                     entry.notifyFullScreenIntentLaunched();
                 } catch (PendingIntent.CanceledException e) {
@@ -2021,6 +1993,17 @@
         mHeadsUpManager.releaseAllImmediately();
     }
 
+    void wakeUpForFullScreenIntent() {
+        if (isGoingToSleep() || mDozing) {
+            mPowerManager.wakeUp(
+                    SystemClock.uptimeMillis(),
+                    PowerManager.WAKE_REASON_APPLICATION,
+                    "com.android.systemui:full_screen_intent");
+            mWakeUpComingFromTouch = false;
+            mWakeUpTouchLocation = null;
+        }
+    }
+
     void makeExpandedVisible(boolean force) {
         if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
         if (!force && (mExpandedVisible || !mCommandQueue.panelsEnabled())) {
@@ -2315,7 +2298,8 @@
     }
 
     @Override
-    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+    public void dump(FileDescriptor fd, PrintWriter pwOriginal, String[] args) {
+        IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
         synchronized (mQueueLock) {
             pw.println("Current Status Bar state:");
             pw.println("  mExpandedVisible=" + mExpandedVisible);
@@ -2356,14 +2340,12 @@
         }
         pw.println("  mStackScroller: ");
         if (mStackScroller != null) {
-            DumpUtilsKt.withIndenting(pw, ipw -> {
-                // Triple indent until we rewrite the rest of this dump()
-                ipw.increaseIndent();
-                ipw.increaseIndent();
-                mStackScroller.dump(fd, ipw, args);
-                ipw.decreaseIndent();
-                ipw.decreaseIndent();
-            });
+            // Double indent until we rewrite the rest of this dump()
+            pw.increaseIndent();
+            pw.increaseIndent();
+            mStackScroller.dump(fd, pw, args);
+            pw.decreaseIndent();
+            pw.decreaseIndent();
         }
         pw.println("  Theme:");
         String nightMode = mUiModeManager == null ? "null" : mUiModeManager.getNightMode() + "";
@@ -3283,6 +3265,10 @@
             }
             return true;
         }
+        if (mNotificationPanelViewController.isQsCustomizing()) {
+            mNotificationPanelViewController.closeQsCustomizer();
+            return true;
+        }
         if (mNotificationPanelViewController.isQsExpanded()) {
             if (mNotificationPanelViewController.isQsDetailShowing()) {
                 mNotificationPanelViewController.closeQsDetail();
@@ -3546,7 +3532,7 @@
             DejankUtils.startDetectingBlockingIpcs(tag);
             updateRevealEffect(false /* wakingUp */);
             updateNotificationPanelTouchState();
-            notifyHeadsUpGoingToSleep();
+            maybeEscalateHeadsUp();
             dismissVolumeDialog();
             mWakeUpCoordinator.setFullyAwake(false);
             mBypassHeadsUpNotifier.setFullyAwake(false);
@@ -3832,6 +3818,7 @@
     private final DeviceProvisionedController mDeviceProvisionedController;
 
     private final NavigationBarController mNavigationBarController;
+    private final AccessibilityFloatingMenuController mAccessibilityFloatingMenuController;
 
     // UI-specific methods
 
@@ -4091,10 +4078,6 @@
         }
     }
 
-    protected void notifyHeadsUpGoingToSleep() {
-        maybeEscalateHeadsUp();
-    }
-
     /**
      * @return Whether the security bouncer from Keyguard is showing.
      */
@@ -4270,13 +4253,6 @@
         }
     };
 
-    BroadcastReceiver mTaskbarChangeReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            mBubblesOptional.ifPresent(bubbles -> bubbles.onTaskbarChanged(intent.getExtras()));
-        }
-    };
-
     private final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
         @Override
         public void onConfigChanged(Configuration newConfig) {
@@ -4287,7 +4263,7 @@
                 Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
             }
 
-            if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+            if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
                 mViewHierarchyManager.updateRowStates();
             }
             mScreenPinningRequest.onConfigurationChanged();
@@ -4371,7 +4347,7 @@
 
                 @Override
                 public void onDozeAmountChanged(float linear, float eased) {
-                    if (mFeatureFlags.useNewLockscreenAnimations()
+                    if (mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)
                             && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)
                             && !mBiometricUnlockController.isWakeAndUnlock()) {
                         mLightRevealScrim.setRevealAmount(1f - linear);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
index a77a097..ae3b7ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarCommandQueueCallbacks.java
@@ -30,11 +30,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Resources;
-import android.media.AudioAttributes;
 import android.os.Bundle;
 import android.os.PowerManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.util.Log;
@@ -106,10 +106,8 @@
     private final VibrationEffect mCameraLaunchGestureVibrationEffect;
 
 
-    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-            .build();
+    private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
+            VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
 
     @Inject
     StatusBarCommandQueueCallbacks(
@@ -611,9 +609,9 @@
     }
 
     private void vibrateForCameraGesture() {
-        // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
         mVibratorOptional.ifPresent(
-                v -> v.vibrate(mCameraLaunchGestureVibrationEffect, VIBRATION_ATTRIBUTES));
+                v -> v.vibrate(mCameraLaunchGestureVibrationEffect,
+                        HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES));
     }
 
     private static VibrationEffect getCameraGestureVibrationEffect(
@@ -627,6 +625,8 @@
                     .compose();
         }
         if (vibratorOptional.isPresent() && vibratorOptional.get().hasAmplitudeControl()) {
+            // Make sure to pass -1 for repeat so VibratorManagerService doesn't stop us when going
+            // to sleep.
             return VibrationEffect.createWaveform(
                     StatusBar.CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS,
                     StatusBar.CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES,
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 48fe774..81fb903 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -38,6 +38,7 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.demomode.DemoModeCommandReceiver;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
 import com.android.systemui.statusbar.StatusBarIconView;
@@ -353,7 +354,8 @@
 
         private StatusBarMobileView onCreateStatusBarMobileView(String slot) {
             StatusBarMobileView view = StatusBarMobileView.fromContext(
-                            mContext, slot, mFeatureFlags.isCombinedStatusBarSignalIconsEnabled());
+                            mContext, slot,
+                    mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS));
             return view;
         }
 
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 7ab4a1e..e2bf0db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -441,6 +441,8 @@
      * dragging it and translation should be deferred {@see KeyguardBouncer#show(boolean, boolean)}
      */
     public void showBouncer(boolean scrimmed) {
+        resetAlternateAuth(false);
+
         if (mShowing && !mBouncer.isShowing()) {
             mBouncer.show(false /* resetSecuritySelection */, scrimmed);
         }
@@ -553,12 +555,13 @@
     public void onStartedWakingUp() {
         mStatusBar.getNotificationShadeWindowView().getWindowInsetsController()
                 .setAnimationsDisabled(false);
-        View currentView = getCurrentNavBarView();
-        if (currentView != null) {
-            currentView.animate()
-                    .alpha(1f)
-                    .setDuration(NAV_BAR_CONTENT_FADE_DURATION)
-                    .start();
+        NavigationBarView navBarView = mStatusBar.getNavigationBarView();
+        if (navBarView != null) {
+            navBarView.forEachView(view ->
+                    view.animate()
+                            .alpha(1f)
+                            .setDuration(NAV_BAR_CONTENT_FADE_DURATION)
+                            .start());
         }
     }
 
@@ -566,12 +569,13 @@
     public void onStartedGoingToSleep() {
         mStatusBar.getNotificationShadeWindowView().getWindowInsetsController()
                 .setAnimationsDisabled(true);
-        View currentView = getCurrentNavBarView();
-        if (currentView != null) {
-            currentView.animate()
-                    .alpha(0f)
-                    .setDuration(NAV_BAR_CONTENT_FADE_DURATION)
-                    .start();
+        NavigationBarView navBarView = mStatusBar.getNavigationBarView();
+        if (navBarView != null) {
+            navBarView.forEachView(view ->
+                    view.animate()
+                            .alpha(0f)
+                            .setDuration(NAV_BAR_CONTENT_FADE_DURATION)
+                            .start());
         }
     }
 
@@ -1013,17 +1017,6 @@
         mStatusBar.onKeyguardViewManagerStatesUpdated();
     }
 
-    /**
-     * Updates the visibility of the nav bar content views.
-     */
-    private void updateNavigationBarContentVisibility(boolean navBarContentVisible) {
-        final NavigationBarView navBarView = mStatusBar.getNavigationBarView();
-        if (navBarView != null && navBarView.getCurrentView() != null) {
-            final View currentView = navBarView.getCurrentView();
-            currentView.setVisibility(navBarContentVisible ? View.VISIBLE : View.INVISIBLE);
-        }
-    }
-
     private View getCurrentNavBarView() {
         final NavigationBarView navBarView = mStatusBar.getNavigationBarView();
         return navBarView != null ? navBarView.getCurrentView() : null;
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 c2e790f..863ce57 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationActivityStarter.java
@@ -41,6 +41,8 @@
 import android.util.EventLog;
 import android.view.View;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.statusbar.NotificationVisibility;
@@ -52,7 +54,6 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
@@ -60,6 +61,7 @@
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -117,7 +119,7 @@
     private final StatusBarRemoteInputCallback mStatusBarRemoteInputCallback;
     private final ActivityIntentHelper mActivityIntentHelper;
 
-    private final FeatureFlags mFeatureFlags;
+    private final NotifPipelineFlags mNotifPipelineFlags;
     private final MetricsLogger mMetricsLogger;
     private final StatusBarNotificationActivityStarterLogger mLogger;
 
@@ -156,12 +158,10 @@
             LockPatternUtils lockPatternUtils,
             StatusBarRemoteInputCallback remoteInputCallback,
             ActivityIntentHelper activityIntentHelper,
-
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             MetricsLogger metricsLogger,
             StatusBarNotificationActivityStarterLogger logger,
             OnUserInteractionCallback onUserInteractionCallback,
-
             StatusBar statusBar,
             NotificationPresenter presenter,
             NotificationPanelViewController panel,
@@ -193,7 +193,7 @@
         mStatusBarRemoteInputCallback = remoteInputCallback;
         mActivityIntentHelper = activityIntentHelper;
 
-        mFeatureFlags = featureFlags;
+        mNotifPipelineFlags = notifPipelineFlags;
         mMetricsLogger = metricsLogger;
         mLogger = logger;
         mOnUserInteractionCallback = onUserInteractionCallback;
@@ -205,7 +205,7 @@
         mActivityLaunchAnimator = activityLaunchAnimator;
         mNotificationAnimationProvider = notificationAnimationProvider;
 
-        if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
             mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
                 @Override
                 public void onPendingEntryAdded(NotificationEntry entry) {
@@ -590,7 +590,8 @@
         }
     }
 
-    private void handleFullScreenIntent(NotificationEntry entry) {
+    @VisibleForTesting
+    void handleFullScreenIntent(NotificationEntry entry) {
         if (mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(entry)) {
             if (shouldSuppressFullScreenIntent(entry)) {
                 mLogger.logFullScreenIntentSuppressedByDnD(entry.getKey());
@@ -614,6 +615,7 @@
                 try {
                     EventLog.writeEvent(EventLogTags.SYSUI_FULLSCREEN_NOTIFICATION,
                             entry.getKey());
+                    mStatusBar.wakeUpForFullScreenIntent();
                     fullscreenIntent.send();
                     entry.notifyFullScreenIntentLaunched();
                     mMetricsLogger.count("note_fullscreen", 1);
@@ -659,7 +661,7 @@
     // --------------------- NotificationEntryManager/NotifPipeline methods ------------------------
 
     private int getVisibleNotificationsCount() {
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) {
             return mNotifPipeline.getShadeListCount();
         } else {
             return mEntryManager.getActiveNotificationsCount();
@@ -696,13 +698,11 @@
         private final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
         private final LockPatternUtils mLockPatternUtils;
         private final StatusBarRemoteInputCallback mRemoteInputCallback;
-        private final ActivityIntentHelper mActivityIntentHelper;
-
-        private final FeatureFlags mFeatureFlags;
+        private final ActivityIntentHelper mActivityIntentHelper;;
         private final MetricsLogger mMetricsLogger;
         private final StatusBarNotificationActivityStarterLogger mLogger;
         private final OnUserInteractionCallback mOnUserInteractionCallback;
-
+        private final NotifPipelineFlags mNotifPipelineFlags;
         private StatusBar mStatusBar;
         private NotificationPresenter mNotificationPresenter;
         private NotificationPanelViewController mNotificationPanelViewController;
@@ -736,8 +736,7 @@
                 LockPatternUtils lockPatternUtils,
                 StatusBarRemoteInputCallback remoteInputCallback,
                 ActivityIntentHelper activityIntentHelper,
-
-                FeatureFlags featureFlags,
+                NotifPipelineFlags notifPipelineFlags,
                 MetricsLogger metricsLogger,
                 StatusBarNotificationActivityStarterLogger logger,
                 OnUserInteractionCallback onUserInteractionCallback) {
@@ -767,8 +766,7 @@
             mLockPatternUtils = lockPatternUtils;
             mRemoteInputCallback = remoteInputCallback;
             mActivityIntentHelper = activityIntentHelper;
-
-            mFeatureFlags = featureFlags;
+            mNotifPipelineFlags = notifPipelineFlags;
             mMetricsLogger = metricsLogger;
             mLogger = logger;
             mOnUserInteractionCallback = onUserInteractionCallback;
@@ -832,7 +830,7 @@
                     mLockPatternUtils,
                     mRemoteInputCallback,
                     mActivityIntentHelper,
-                    mFeatureFlags,
+                    mNotifPipelineFlags,
                     mMetricsLogger,
                     mLogger,
                     mOnUserInteractionCallback,
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 7c0f923..c8e1cdc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -41,7 +41,6 @@
 import com.android.systemui.ForegroundServiceNotificationListener;
 import com.android.systemui.InitController;
 import com.android.systemui.R;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.statusbar.CommandQueue;
@@ -57,6 +56,7 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.AboveShelfObserver;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
@@ -99,7 +99,6 @@
     private final DozeScrimController mDozeScrimController;
     private final ScrimController mScrimController;
     private final KeyguardIndicationController mKeyguardIndicationController;
-    private final FeatureFlags mFeatureFlags;
     private final StatusBar mStatusBar;
     private final ShadeController mShadeController;
     private final LockscreenShadeTransitionController mShadeTransitionController;
@@ -108,6 +107,7 @@
     private final AccessibilityManager mAccessibilityManager;
     private final KeyguardManager mKeyguardManager;
     private final NotificationShadeWindowController mNotificationShadeWindowController;
+    private final NotifPipelineFlags mNotifPipelineFlags;
     private final IStatusBarService mBarService;
     private final DynamicPrivacyController mDynamicPrivacyController;
     private boolean mReinflateNotificationsOnUserSwitched;
@@ -127,7 +127,6 @@
             DynamicPrivacyController dynamicPrivacyController,
             KeyguardStateController keyguardStateController,
             KeyguardIndicationController keyguardIndicationController,
-            FeatureFlags featureFlags,
             StatusBar statusBar,
             ShadeController shadeController,
             LockscreenShadeTransitionController shadeTransitionController,
@@ -144,13 +143,13 @@
             InitController initController,
             NotificationInterruptStateProvider notificationInterruptStateProvider,
             NotificationRemoteInputManager remoteInputManager,
-            ConfigurationController configurationController) {
+            ConfigurationController configurationController,
+            NotifPipelineFlags notifPipelineFlags) {
         mKeyguardStateController = keyguardStateController;
         mNotificationPanel = panel;
         mHeadsUpManager = headsUp;
         mDynamicPrivacyController = dynamicPrivacyController;
         mKeyguardIndicationController = keyguardIndicationController;
-        mFeatureFlags = featureFlags;
         // TODO: use KeyguardStateController#isOccluded to remove this dependency
         mStatusBar = statusBar;
         mShadeController = shadeController;
@@ -167,6 +166,7 @@
         mLockscreenGestureLogger = lockscreenGestureLogger;
         mAboveShelfObserver = new AboveShelfObserver(stackScrollerController.getView());
         mNotificationShadeWindowController = notificationShadeWindowController;
+        mNotifPipelineFlags = notifPipelineFlags;
         mAboveShelfObserver.setListener(statusBarWindow.findViewById(
                 R.id.notification_container_parent));
         mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
@@ -192,10 +192,11 @@
         initController.addPostInitTask(() -> {
             mKeyguardIndicationController.init();
             mViewHierarchyManager.setUpWithPresenter(this,
+                    stackScrollerController.getNotifStackController(),
                     stackScrollerController.getNotificationListContainer());
             mNotifShadeEventSource.setShadeEmptiedCallback(this::maybeClosePanelForShadeEmptied);
             mNotifShadeEventSource.setNotifRemovedByUserCallback(this::maybeEndAmbientPulse);
-            if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+            if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
                 mEntryManager.setUpWithPresenter(this);
                 mEntryManager.addNotificationLifetimeExtender(mHeadsUpManager);
                 mEntryManager.addNotificationLifetimeExtender(mGutsManager);
@@ -232,7 +233,7 @@
     @Override
     public void onDensityOrFontScaleChanged() {
         // TODO(b/145659174): Remove legacy pipeline code
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) return;
         MessagingMessage.dropCache();
         MessagingGroup.dropCache();
         if (!mKeyguardUpdateMonitor.isSwitchingUser()) {
@@ -245,7 +246,7 @@
     @Override
     public void onUiModeChanged() {
         // TODO(b/145659174): Remove legacy pipeline code
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) return;
         if (!mKeyguardUpdateMonitor.isSwitchingUser()) {
             updateNotificationsOnUiModeChanged();
         } else {
@@ -260,7 +261,7 @@
 
     private void updateNotificationsOnUiModeChanged() {
         // TODO(b/145659174): Remove legacy pipeline code
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) return;
         List<NotificationEntry> userNotifications =
                 mEntryManager.getActiveNotificationsForCurrentUser();
         for (int i = 0; i < userNotifications.size(); i++) {
@@ -274,7 +275,7 @@
 
     private void updateNotificationsOnDensityOrFontScaleChanged() {
         // TODO(b/145659174): Remove legacy pipeline code
-        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
+        if (mNotifPipelineFlags.isNewPipelineEnabled()) return;
         List<NotificationEntry> userNotifications =
                 mEntryManager.getActiveNotificationsForCurrentUser();
         for (int i = 0; i < userNotifications.size(); i++) {
@@ -305,7 +306,7 @@
 
     @Override
     public void updateNotificationViews(final String reason) {
-        if (!mFeatureFlags.checkLegacyPipelineEnabled()) {
+        if (!mNotifPipelineFlags.checkLegacyPipelineEnabled()) {
             return;
         }
         // The function updateRowStates depends on both of these being non-null, so check them here.
@@ -328,7 +329,7 @@
         // End old BaseStatusBar.userSwitched
         if (MULTIUSER_DEBUG) mNotificationPanel.setHeaderDebugInfo("USER " + newUserId);
         mCommandQueue.animateCollapsePanels();
-        if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
             if (mReinflateNotificationsOnUserSwitched) {
                 updateNotificationsOnDensityOrFontScaleChanged();
                 mReinflateNotificationsOnUserSwitched = false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
index 9c69f51..b0206f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarSignalPolicy.java
@@ -27,6 +27,7 @@
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.statusbar.connectivity.IconState;
 import com.android.systemui.statusbar.connectivity.MobileDataIndicators;
 import com.android.systemui.statusbar.connectivity.NetworkController;
@@ -72,17 +73,15 @@
     private boolean mHideWifi;
     private boolean mHideEthernet;
     private boolean mActivityEnabled;
-    private boolean mForceHideWifi;
 
     // Track as little state as possible, and only for padding purposes
     private boolean mIsAirplaneMode = false;
     private boolean mIsWifiEnabled = false;
-    private boolean mWifiVisible = false;
 
-    private ArrayList<MobileIconState> mMobileStates = new ArrayList<MobileIconState>();
-    private ArrayList<CallIndicatorIconState> mCallIndicatorStates =
-            new ArrayList<CallIndicatorIconState>();
+    private ArrayList<MobileIconState> mMobileStates = new ArrayList<>();
+    private ArrayList<CallIndicatorIconState> mCallIndicatorStates = new ArrayList<>();
     private WifiIconState mWifiIconState = new WifiIconState();
+    private boolean mInitialized;
 
     @Inject
     public StatusBarSignalPolicy(
@@ -112,9 +111,15 @@
         mSlotCallStrength =
                 mContext.getString(com.android.internal.R.string.status_bar_call_strength);
         mActivityEnabled = mContext.getResources().getBoolean(R.bool.config_showActivity);
+    }
 
-
-        tunerService.addTunable(this, StatusBarIconController.ICON_HIDE_LIST);
+    /** Call to initilaize and register this classw with the system. */
+    public void init() {
+        if (mInitialized) {
+            return;
+        }
+        mInitialized = true;
+        mTunerService.addTunable(this, StatusBarIconController.ICON_HIDE_LIST);
         mNetworkController.addCallback(this);
         mSecurityController.addCallback(this);
     }
@@ -162,7 +167,7 @@
             mHideAirplane = hideAirplane;
             mHideMobile = hideMobile;
             mHideEthernet = hideEthernet;
-            mHideWifi = hideWifi || mForceHideWifi;
+            mHideWifi = hideWifi;
             // Re-register to get new callbacks.
             mNetworkController.removeCallback(this);
             mNetworkController.addCallback(this);
@@ -375,7 +380,7 @@
     @Override
     public void setConnectivityStatus(boolean noDefaultNetwork, boolean noValidatedNetwork,
             boolean noNetworksAvailable) {
-        if (!mFeatureFlags.isCombinedStatusBarSignalIconsEnabled()) {
+        if (!mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)) {
             return;
         }
         if (DEBUG) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index cf4aaba..ed52a81 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -36,6 +36,8 @@
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 
+import androidx.annotation.Nullable;
+
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.animation.DialogListener;
@@ -218,6 +220,19 @@
         }
     }
 
+    /**
+     * Dismiss this dialog. If it was launched from another dialog using
+     * {@link com.android.systemui.animation.DialogLaunchAnimator#showFromView} with a
+     * non-{@code null} {@code parentHostDialog} parameter, also dismisses the stack of dialogs,
+     * animating back to the original touchSurface.
+     */
+    public void dismissStack() {
+        for (DialogListener listener : new LinkedHashSet<>(mDialogListeners)) {
+            listener.prepareForStackDismiss();
+        }
+        dismiss();
+    }
+
     @Override
     public void hide() {
         super.hide();
@@ -290,13 +305,32 @@
      * the screen off / close system dialogs broadcast.
      * <p>
      * <strong>Note:</strong> Don't call dialog.setOnDismissListener() after
-     * calling this because it causes a leak of BroadcastReceiver.
+     * calling this because it causes a leak of BroadcastReceiver. Instead, call the version that
+     * takes an extra Runnable as a parameter.
      *
      * @param dialog The dialog to be associated with the listener.
      */
     public static void registerDismissListener(Dialog dialog) {
+        registerDismissListener(dialog, null);
+    }
+
+
+    /**
+     * Registers a listener that dismisses the given dialog when it receives
+     * the screen off / close system dialogs broadcast.
+     * <p>
+     * <strong>Note:</strong> Don't call dialog.setOnDismissListener() after
+     * calling this because it causes a leak of BroadcastReceiver.
+     *
+     * @param dialog The dialog to be associated with the listener.
+     * @param dismissAction An action to run when the dialog is dismissed.
+     */
+    public static void registerDismissListener(Dialog dialog, @Nullable Runnable dismissAction) {
         DismissReceiver dismissReceiver = new DismissReceiver(dialog);
-        dialog.setOnDismissListener(d -> dismissReceiver.unregister());
+        dialog.setOnDismissListener(d -> {
+            dismissReceiver.unregister();
+            if (dismissAction != null) dismissAction.run();
+        });
         dismissReceiver.register();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java
index e06605e..375641f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarComponent.java
@@ -29,6 +29,7 @@
 import com.android.systemui.statusbar.phone.StatusBarCommandQueueCallbacks;
 import com.android.systemui.statusbar.phone.StatusBarDemoMode;
 import com.android.systemui.statusbar.phone.StatusBarHeadsUpChangeListener;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
 
 import java.lang.annotation.Documented;
 import java.lang.annotation.Retention;
@@ -38,7 +39,13 @@
 import dagger.Subcomponent;
 
 /**
- * Dagger subcomponent tied to the lifecycle of StatusBar views.
+ * Dagger subcomponent for classes (semi-)related to the status bar. The component is created once
+ * inside {@link com.android.systemui.statusbar.phone.StatusBar} and never re-created.
+ *
+ * TODO(b/197137564): This should likely be re-factored a bit. It includes classes that aren't
+ * directly related to status bar functionality, like multiple notification classes. And, the fact
+ * that it has many getter methods indicates that we need to access many of these classes from
+ * outside the component. Should more items be moved *into* this component to avoid so many getters?
  */
 @Subcomponent(modules = {StatusBarViewModule.class})
 @StatusBarComponent.StatusBarScope
@@ -121,4 +128,10 @@
      */
     @StatusBarScope
     SplitShadeHeaderController getSplitShadeHeaderController();
+
+    /**
+     * Creates a new {@link CollapsedStatusBarFragment} each time it's called. See
+     * {@link StatusBarViewModule#createCollapsedStatusBarFragment}.
+     */
+    CollapsedStatusBarFragment createCollapsedStatusBarFragment();
 }
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 3259f6b..33171b2 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
@@ -28,6 +28,7 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.InitController;
+import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -39,6 +40,7 @@
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
@@ -64,6 +66,7 @@
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
@@ -75,7 +78,6 @@
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.BiometricUnlockController;
-import com.android.systemui.statusbar.phone.CollapsedStatusBarFragmentLogger;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.DozeScrimController;
 import com.android.systemui.statusbar.phone.DozeServiceHost;
@@ -88,7 +90,6 @@
 import com.android.systemui.statusbar.phone.LockscreenWallpaper;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
-import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -97,8 +98,10 @@
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
 import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
+import com.android.systemui.statusbar.phone.StatusBarSignalPolicy;
 import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -141,10 +144,12 @@
     static StatusBar provideStatusBar(
             Context context,
             NotificationsController notificationsController,
+            FragmentService fragmentService,
             LightBarController lightBarController,
             AutoHideController autoHideController,
             StatusBarWindowController statusBarWindowController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
+            StatusBarSignalPolicy statusBarSignalPolicy,
             PulseExpansionHandler pulseExpansionHandler,
             NotificationWakeUpCoordinator notificationWakeUpCoordinator,
             KeyguardBypassController keyguardBypassController,
@@ -181,6 +186,7 @@
             VisualStabilityManager visualStabilityManager,
             DeviceProvisionedController deviceProvisionedController,
             NavigationBarController navigationBarController,
+            AccessibilityFloatingMenuController accessibilityFloatingMenuController,
             Lazy<AssistManager> assistManagerLazy,
             ConfigurationController configurationController,
             NotificationShadeWindowController notificationShadeWindowController,
@@ -212,7 +218,6 @@
             ExtensionController extensionController,
             UserInfoControllerImpl userInfoControllerImpl,
             OperatorNameViewController.Factory operatorNameViewControllerFactory,
-            PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory,
             PhoneStatusBarPolicy phoneStatusBarPolicy,
             KeyguardIndicationController keyguardIndicationController,
             DemoModeController demoModeController,
@@ -237,14 +242,17 @@
             Optional<StartingSurface> startingSurfaceOptional,
             TunerService tunerService,
             DumpManager dumpManager,
-            ActivityLaunchAnimator activityLaunchAnimator) {
+            ActivityLaunchAnimator activityLaunchAnimator,
+            NotifPipelineFlags notifPipelineFlags) {
         return new StatusBar(
                 context,
                 notificationsController,
+                fragmentService,
                 lightBarController,
                 autoHideController,
                 statusBarWindowController,
                 keyguardUpdateMonitor,
+                statusBarSignalPolicy,
                 pulseExpansionHandler,
                 notificationWakeUpCoordinator,
                 keyguardBypassController,
@@ -281,6 +289,7 @@
                 visualStabilityManager,
                 deviceProvisionedController,
                 navigationBarController,
+                accessibilityFloatingMenuController,
                 assistManagerLazy,
                 configurationController,
                 notificationShadeWindowController,
@@ -311,7 +320,6 @@
                 extensionController,
                 userInfoControllerImpl,
                 operatorNameViewControllerFactory,
-                phoneStatusBarViewControllerFactory,
                 phoneStatusBarPolicy,
                 keyguardIndicationController,
                 demoModeController,
@@ -336,7 +344,8 @@
                 startingSurfaceOptional,
                 tunerService,
                 dumpManager,
-                activityLaunchAnimator
+                activityLaunchAnimator,
+                notifPipelineFlags
         );
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
index 2765fe3..beed60b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
@@ -17,6 +17,8 @@
 package com.android.systemui.statusbar.phone.dagger;
 
 import android.annotation.Nullable;
+import android.content.ContentResolver;
+import android.os.Handler;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewStub;
@@ -24,26 +26,55 @@
 import com.android.keyguard.LockIconView;
 import com.android.systemui.R;
 import com.android.systemui.battery.BatteryMeterView;
+import com.android.systemui.battery.BatteryMeterViewController;
 import com.android.systemui.biometrics.AuthRippleView;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.NotificationShelfController;
+import com.android.systemui.statusbar.OperatorNameViewController;
+import com.android.systemui.statusbar.connectivity.NetworkController;
+import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
 import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.NotificationPanelView;
+import com.android.systemui.statusbar.phone.NotificationPanelViewController;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
 import com.android.systemui.statusbar.phone.TapAgainView;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
+import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
+import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.tuner.TunerService;
+
+import java.util.Optional;
 
 import javax.inject.Named;
 
+import dagger.Lazy;
 import dagger.Module;
 import dagger.Provides;
 
-@Module
+@Module(subcomponents = StatusBarFragmentComponent.class)
 public abstract class StatusBarViewModule {
 
     public static final String SPLIT_SHADE_HEADER = "split_shade_header";
+    private static final String SPLIT_SHADE_BATTERY_VIEW = "split_shade_battery_view";
+    public static final String SPLIT_SHADE_BATTERY_CONTROLLER = "split_shade_battery_controller";
 
     /** */
     @Provides
@@ -132,7 +163,7 @@
             NotificationShadeWindowView notificationShadeWindowView,
             FeatureFlags featureFlags) {
         ViewStub stub = notificationShadeWindowView.findViewById(R.id.qs_header_stub);
-        int layoutId = featureFlags.useCombinedQSHeaders()
+        int layoutId = featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)
                 ? R.layout.combined_qs_header
                 : R.layout.split_shade_header;
         stub.setLayoutResource(layoutId);
@@ -143,10 +174,34 @@
     /** */
     @Provides
     @StatusBarComponent.StatusBarScope
+    @Named(SPLIT_SHADE_BATTERY_VIEW)
     static BatteryMeterView getBatteryMeterView(@Named(SPLIT_SHADE_HEADER) View view) {
         return view.findViewById(R.id.batteryRemainingIcon);
     }
 
+    @Provides
+    @StatusBarComponent.StatusBarScope
+    @Named(SPLIT_SHADE_BATTERY_CONTROLLER)
+    static BatteryMeterViewController getBatteryMeterViewController(
+            @Named(SPLIT_SHADE_BATTERY_VIEW) BatteryMeterView batteryMeterView,
+            ConfigurationController configurationController,
+            TunerService tunerService,
+            BroadcastDispatcher broadcastDispatcher,
+            @Main Handler mainHandler,
+            ContentResolver contentResolver,
+            BatteryController batteryController
+    ) {
+        return new BatteryMeterViewController(
+                batteryMeterView,
+                configurationController,
+                tunerService,
+                broadcastDispatcher,
+                mainHandler,
+                contentResolver,
+                batteryController);
+
+    }
+
     /** */
     @Provides
     @StatusBarComponent.StatusBarScope
@@ -161,4 +216,54 @@
             NotificationShadeWindowView notificationShadeWindowView) {
         return notificationShadeWindowView.findViewById(R.id.notification_container_parent);
     }
+
+    /**
+     * Creates a new {@link CollapsedStatusBarFragment}.
+     *
+     * **IMPORTANT**: This method intentionally does not have
+     * {@link StatusBarComponent.StatusBarScope}, which means a new fragment *will* be created each
+     * time this method is called. This is intentional because we need fragments to re-created in
+     * certain lifecycle scenarios.
+     *
+     * **IMPORTANT**: This method also intentionally does not have a {@link Provides} annotation. If
+     * you need to get access to a {@link CollapsedStatusBarFragment}, go through
+     * {@link StatusBarFragmentComponent} instead.
+     */
+    public static CollapsedStatusBarFragment createCollapsedStatusBarFragment(
+            StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
+            OngoingCallController ongoingCallController,
+            SystemStatusAnimationScheduler animationScheduler,
+            StatusBarLocationPublisher locationPublisher,
+            NotificationIconAreaController notificationIconAreaController,
+            PanelExpansionStateManager panelExpansionStateManager,
+            FeatureFlags featureFlags,
+            StatusBarIconController statusBarIconController,
+            StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
+            KeyguardStateController keyguardStateController,
+            NotificationPanelViewController notificationPanelViewController,
+            NetworkController networkController,
+            StatusBarStateController statusBarStateController,
+            Lazy<Optional<StatusBar>> statusBarOptionalLazy,
+            CommandQueue commandQueue,
+            CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,
+            OperatorNameViewController.Factory operatorNameViewControllerFactory
+    ) {
+        return new CollapsedStatusBarFragment(statusBarFragmentComponentFactory,
+                ongoingCallController,
+                animationScheduler,
+                locationPublisher,
+                notificationIconAreaController,
+                panelExpansionStateManager,
+                featureFlags,
+                statusBarIconController,
+                statusBarHideIconsForBouncerManager,
+                keyguardStateController,
+                notificationPanelViewController,
+                networkController,
+                statusBarStateController,
+                statusBarOptionalLazy,
+                commandQueue,
+                collapsedStatusBarFragmentLogger,
+                operatorNameViewControllerFactory);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
similarity index 92%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 2b62e0b..2762b4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -12,7 +12,7 @@
  * permissions and limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone;
+package com.android.systemui.statusbar.phone.fragment;
 
 import static android.app.StatusBarManager.DISABLE2_SYSTEM_ICONS;
 import static android.app.StatusBarManager.DISABLE_CLOCK;
@@ -52,7 +52,15 @@
 import com.android.systemui.statusbar.connectivity.SignalCallback;
 import com.android.systemui.statusbar.events.SystemStatusAnimationCallback;
 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
+import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.PhoneStatusBarView;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarIconController.DarkIconManager;
+import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
@@ -83,9 +91,11 @@
     public static final String STATUS_BAR_ICON_MANAGER_TAG = "status_bar_icon_manager";
     public static final int FADE_IN_DURATION = 320;
     public static final int FADE_IN_DELAY = 50;
+    private StatusBarFragmentComponent mStatusBarFragmentComponent;
     private PhoneStatusBarView mStatusBar;
     private final StatusBarStateController mStatusBarStateController;
     private final KeyguardStateController mKeyguardStateController;
+    private final NotificationPanelViewController mNotificationPanelViewController;
     private final NetworkController mNetworkController;
     private LinearLayout mSystemIconArea;
     private View mClockView;
@@ -96,6 +106,7 @@
     private int mDisabled2;
     private Lazy<Optional<StatusBar>> mStatusBarOptionalLazy;
     private DarkIconManager mDarkIconManager;
+    private final StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory;
     private final CommandQueue mCommandQueue;
     private final CollapsedStatusBarFragmentLogger mCollapsedStatusBarFragmentLogger;
     private final OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
@@ -127,6 +138,7 @@
 
     @Inject
     public CollapsedStatusBarFragment(
+            StatusBarFragmentComponent.Factory statusBarFragmentComponentFactory,
             OngoingCallController ongoingCallController,
             SystemStatusAnimationScheduler animationScheduler,
             StatusBarLocationPublisher locationPublisher,
@@ -136,6 +148,7 @@
             StatusBarIconController statusBarIconController,
             StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
             KeyguardStateController keyguardStateController,
+            NotificationPanelViewController notificationPanelViewController,
             NetworkController networkController,
             StatusBarStateController statusBarStateController,
             Lazy<Optional<StatusBar>> statusBarOptionalLazy,
@@ -143,6 +156,7 @@
             CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger,
             OperatorNameViewController.Factory operatorNameViewControllerFactory
     ) {
+        mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory;
         mOngoingCallController = ongoingCallController;
         mAnimationScheduler = animationScheduler;
         mLocationPublisher = locationPublisher;
@@ -152,6 +166,7 @@
         mStatusBarIconController = statusBarIconController;
         mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
         mKeyguardStateController = keyguardStateController;
+        mNotificationPanelViewController = notificationPanelViewController;
         mNetworkController = networkController;
         mStatusBarStateController = statusBarStateController;
         mStatusBarOptionalLazy = statusBarOptionalLazy;
@@ -169,6 +184,9 @@
     @Override
     public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
         super.onViewCreated(view, savedInstanceState);
+        mStatusBarFragmentComponent = mStatusBarFragmentComponentFactory.create(this);
+        mStatusBarFragmentComponent.init();
+
         mStatusBar = (PhoneStatusBarView) view;
         View contents = mStatusBar.findViewById(R.id.status_bar_contents);
         contents.addOnLayoutChangeListener(mStatusBarLayoutListener);
@@ -252,6 +270,17 @@
         updateNotificationIconAreaAndCallChip(mDisabled1, false);
     }
 
+    /**
+     * Returns the dagger component for this fragment.
+     *
+     * TODO(b/205609837): Eventually, the dagger component should encapsulate all status bar
+     *   fragment functionality and we won't need to expose it here anymore.
+     */
+    @Nullable
+    public StatusBarFragmentComponent getStatusBarFragmentComponent() {
+        return mStatusBarFragmentComponent;
+    }
+
     @Override
     public void disable(int displayId, int state1, int state2, boolean animate) {
         if (displayId != getContext().getDisplayId()) {
@@ -300,8 +329,8 @@
     }
 
     protected int adjustDisableFlags(int state) {
-        boolean headsUpVisible = mStatusBarOptionalLazy.get()
-                .map(StatusBar::headsUpShouldBeVisible).orElse(false);
+        boolean headsUpVisible =
+                mStatusBarFragmentComponent.getHeadsUpAppearanceController().shouldBeVisible();
         if (headsUpVisible) {
             state |= DISABLE_CLOCK;
         }
@@ -329,8 +358,7 @@
         // The shelf will be hidden when dozing with a custom clock, we must show notification
         // icons in this occasion.
         if (mStatusBarStateController.isDozing()
-                && mStatusBarOptionalLazy.get().map(
-                        sb -> sb.getPanelController().hasCustomClock()).orElse(false)) {
+                && mNotificationPanelViewController.hasCustomClock()) {
             state |= DISABLE_CLOCK | DISABLE_SYSTEM_INFO;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
similarity index 97%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLogger.kt
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
index 4d472e4..9ae378f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLogger.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone
+package com.android.systemui.statusbar.phone.fragment
 
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.LogLevel
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
new file mode 100644
index 0000000..3656ed1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentComponent.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2021 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.phone.fragment.dagger;
+
+import com.android.systemui.battery.BatteryMeterViewController;
+import com.android.systemui.dagger.qualifiers.RootView;
+import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
+import com.android.systemui.statusbar.phone.PhoneStatusBarView;
+import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
+
+import dagger.BindsInstance;
+import dagger.Subcomponent;
+
+/**
+ * A subcomponent that gets re-created each time we create a new {@link CollapsedStatusBarFragment}.
+ *
+ * This component will also re-create all classes that depend on {@link CollapsedStatusBarFragment}
+ * and friends. Specifically, the fragment creates a new {@link PhoneStatusBarView} and multiple
+ * controllers need access to that view, so those controllers will be re-created whenever the
+ * fragment is recreated.
+ *
+ * Note that this is completely separate from
+ * {@link com.android.systemui.statusbar.phone.dagger.StatusBarComponent}. This component gets
+ * re-created on each new fragment creation, whereas
+ * {@link com.android.systemui.statusbar.phone.dagger.StatusBarComponent} is only created once in
+ * {@link com.android.systemui.statusbar.phone.StatusBar} and never re-created.
+ */
+
+@Subcomponent(modules = {StatusBarFragmentModule.class})
+@StatusBarFragmentScope
+public interface StatusBarFragmentComponent {
+    /** Simple factory. */
+    @Subcomponent.Factory
+    interface Factory {
+        StatusBarFragmentComponent create(
+                @BindsInstance CollapsedStatusBarFragment collapsedStatusBarFragment);
+    }
+
+    /**
+     * Initialize anything extra for the component. Must be called after the component is created.
+     */
+    default void init() {
+        // No one accesses this controller, so we need to make sure we reference it here so it does
+        // get initialized.
+        getBatteryMeterViewController().init();
+        getHeadsUpAppearanceController().init();
+        getPhoneStatusBarViewController().init();
+    }
+
+    /** */
+    @StatusBarFragmentScope
+    BatteryMeterViewController getBatteryMeterViewController();
+
+    /** */
+    @StatusBarFragmentScope
+    @RootView
+    PhoneStatusBarView getPhoneStatusBarView();
+
+    /** */
+    @StatusBarFragmentScope
+    PhoneStatusBarViewController getPhoneStatusBarViewController();
+
+    /** */
+    @StatusBarFragmentScope
+    HeadsUpAppearanceController getHeadsUpAppearanceController();
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
new file mode 100644
index 0000000..d244558
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentModule.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2021 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.phone.fragment.dagger;
+
+import com.android.systemui.R;
+import com.android.systemui.battery.BatteryMeterView;
+import com.android.systemui.dagger.qualifiers.RootView;
+import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.PhoneStatusBarView;
+import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
+
+import dagger.Module;
+import dagger.Provides;
+
+/** Dagger module for {@link StatusBarFragmentComponent}. */
+@Module
+public interface StatusBarFragmentModule {
+    /** */
+    @Provides
+    @RootView
+    @StatusBarFragmentScope
+    static PhoneStatusBarView providePhoneStatusBarView(
+            CollapsedStatusBarFragment collapsedStatusBarFragment) {
+        return (PhoneStatusBarView) collapsedStatusBarFragment.getView();
+    }
+
+    /** */
+    @Provides
+    @StatusBarFragmentScope
+    static BatteryMeterView provideBatteryMeterView(@RootView PhoneStatusBarView view) {
+        return view.findViewById(R.id.battery);
+    }
+
+    /** */
+    @Provides
+    @StatusBarFragmentScope
+    static PhoneStatusBarViewController providePhoneStatusBarViewController(
+            PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory,
+            @RootView PhoneStatusBarView phoneStatusBarView,
+            NotificationPanelViewController notificationPanelViewController) {
+        return phoneStatusBarViewControllerFactory.create(
+                phoneStatusBarView,
+                notificationPanelViewController.getStatusBarTouchEventHandler());
+    }
+}
diff --git a/core/java/android/window/TaskFragmentAppearedInfo.aidl b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.java
similarity index 60%
copy from core/java/android/window/TaskFragmentAppearedInfo.aidl
copy to packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.java
index 3729c09..96cff59 100644
--- a/core/java/android/window/TaskFragmentAppearedInfo.aidl
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/dagger/StatusBarFragmentScope.java
@@ -14,10 +14,19 @@
  * limitations under the License.
  */
 
-package android.window;
+package com.android.systemui.statusbar.phone.fragment.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Scope;
 
 /**
- * Data object for the TaskFragment info provided when a TaskFragment is presented to an organizer.
- * @hide
+ * Scope annotation for singleton items within the {@link StatusBarFragmentComponent}.
  */
-parcelable TaskFragmentAppearedInfo;
+@Documented
+@Retention(RUNTIME)
+@Scope
+public @interface StatusBarFragmentScope {}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
index 1225813..c7f7258 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt
@@ -33,7 +33,6 @@
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.gesture.SwipeStatusBarAwayGestureHandler
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -44,7 +43,7 @@
 import com.android.systemui.util.time.SystemClock
 import java.io.FileDescriptor
 import java.io.PrintWriter
-import java.util.Optional
+import java.util.*
 import java.util.concurrent.Executor
 import javax.inject.Inject
 
@@ -54,7 +53,7 @@
 @SysUISingleton
 class OngoingCallController @Inject constructor(
     private val notifCollection: CommonNotifCollection,
-    private val featureFlags: FeatureFlags,
+    private val ongoingCallFlags: OngoingCallFlags,
     private val systemClock: SystemClock,
     private val activityStarter: ActivityStarter,
     @Main private val mainExecutor: Executor,
@@ -65,7 +64,6 @@
     private val swipeStatusBarAwayGestureHandler: Optional<SwipeStatusBarAwayGestureHandler>,
     private val statusBarStateController: StatusBarStateController,
 ) : CallbackController<OngoingCallListener>, Dumpable {
-
     private var isFullscreen: Boolean = false
     /** Non-null if there's an active call notification. */
     private var callNotificationInfo: CallNotificationInfo? = null
@@ -126,7 +124,7 @@
 
     fun init() {
         dumpManager.registerDumpable(this)
-        if (featureFlags.isOngoingCallStatusBarChipEnabled) {
+        if (ongoingCallFlags.isStatusBarChipEnabled()) {
             notifCollection.addCollectionListener(notifListener)
             statusBarStateController.addCallback(statusBarStateListener)
         }
@@ -218,7 +216,7 @@
 
     private fun updateChipClickListener() {
         if (callNotificationInfo == null) { return }
-        if (isFullscreen && !featureFlags.isOngoingCallInImmersiveChipTapEnabled) {
+        if (isFullscreen && !ongoingCallFlags.isInImmersiveChipTapEnabled()) {
             chipView?.setOnClickListener(null)
         } else {
             val currentChipView = chipView
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt
new file mode 100644
index 0000000..fcfcb8f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallFlags.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 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.phone.ongoingcall
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
+import javax.inject.Inject
+
+@SysUISingleton
+class OngoingCallFlags @Inject constructor(private val featureFlags: FeatureFlags) {
+
+    fun isStatusBarChipEnabled(): Boolean =
+            featureFlags.isEnabled(Flags.ONGOING_CALL_STATUS_BAR_CHIP)
+
+    fun isInImmersiveEnabled(): Boolean = isStatusBarChipEnabled()
+            && featureFlags.isEnabled(Flags.ONGOING_CALL_IN_IMMERSIVE)
+
+    fun isInImmersiveChipTapEnabled(): Boolean = isInImmersiveEnabled()
+            && featureFlags.isEnabled(Flags.ONGOING_CALL_IN_IMMERSIVE_CHIP_TAP)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
index 793a9e1..a857815 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
@@ -37,6 +37,7 @@
 import com.android.systemui.communal.CommunalStateController;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -173,7 +174,7 @@
             }
 
             // Tapping anywhere in the view will open QS user panel
-            if (mFeatureFlags.useNewUserSwitcher()) {
+            if (mFeatureFlags.isEnabled(Flags.NEW_USER_SWITCHER)) {
                 mUserSwitchDialogController.showDialog(mView);
             } else {
                 openQsUserPanel();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index d25013a..46fa20d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -25,9 +25,7 @@
 import android.app.PendingIntent;
 import android.app.RemoteInput;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.PackageManager;
-import android.content.pm.ShortcutManager;
 import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.graphics.BlendMode;
@@ -35,13 +33,9 @@
 import android.graphics.PorterDuff;
 import android.graphics.Rect;
 import android.graphics.drawable.GradientDrawable;
-import android.net.Uri;
-import android.os.Bundle;
-import android.os.SystemClock;
 import android.os.UserHandle;
 import android.text.Editable;
 import android.text.SpannedString;
-import android.text.TextUtils;
 import android.text.TextWatcher;
 import android.util.ArraySet;
 import android.util.AttributeSet;
@@ -78,7 +72,6 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry.EditedSuggestionInfo;
@@ -89,7 +82,6 @@
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
 import java.util.function.Consumer;
 
@@ -107,7 +99,7 @@
 
     private final SendButtonTextWatcher mTextWatcher;
     private final TextView.OnEditorActionListener mEditorActionHandler;
-    private final ArrayList<OnSendRemoteInputListener> mOnSendListeners = new ArrayList<>();
+    private final ArrayList<Runnable> mOnSendListeners = new ArrayList<>();
     private final ArrayList<Consumer<Boolean>> mOnVisibilityChangedListeners = new ArrayList<>();
     private final ArrayList<OnFocusChangeListener> mEditTextFocusChangeListeners =
             new ArrayList<>();
@@ -133,7 +125,6 @@
     private PendingIntent mPendingIntent;
     private RemoteInput mRemoteInput;
     private RemoteInput[] mRemoteInputs;
-    private NotificationRemoteInputManager.BouncerChecker mBouncerChecker;
     private boolean mRemoved;
     private NotificationViewWrapper mWrapper;
 
@@ -178,6 +169,12 @@
         ta.recycle();
     }
 
+    // TODO(b/193539698): move to Controller, since we're just directly accessing a system service
+    /** Hide the IME, if visible. */
+    public void hideIme() {
+        mEditText.hideIme();
+    }
+
     private ColorStateList colorStateListWithDisabledAlpha(int color, int disabledAlpha) {
         return new ColorStateList(new int[][]{
                 new int[]{-com.android.internal.R.attr.state_enabled}, // disabled
@@ -303,6 +300,11 @@
         return mViewController;
     }
 
+    /** Clear the attachment, if present. */
+    public void clearAttachment() {
+        setAttachment(null);
+    }
+
     @VisibleForTesting
     protected void setAttachment(ContentInfo item) {
         if (mEntry.remoteInputAttachment != null && mEntry.remoteInputAttachment != item) {
@@ -339,121 +341,18 @@
         updateSendButton();
     }
 
-    /**
-     * Reply intent
-     * @return returns intent with granted URI permissions that should be used immediately
-     */
-    private Intent prepareRemoteInput() {
-        return mEntry.remoteInputAttachment == null
-                ? prepareRemoteInputFromText()
-                : prepareRemoteInputFromData(mEntry.remoteInputMimeType, mEntry.remoteInputUri);
-    }
-
-    private Intent prepareRemoteInputFromText() {
-        Bundle results = new Bundle();
-        results.putString(mRemoteInput.getResultKey(), mEditText.getText().toString());
-        Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-        RemoteInput.addResultsToIntent(mRemoteInputs, fillInIntent,
-                results);
-
-        mEntry.remoteInputText = mEditText.getText().toString();
-        setAttachment(null);
-        mEntry.remoteInputUri = null;
-        mEntry.remoteInputMimeType = null;
-
-        if (mEntry.editedSuggestionInfo == null) {
-            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT);
-        } else {
-            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE);
-        }
-
-        return fillInIntent;
-    }
-
-    private Intent prepareRemoteInputFromData(String contentType, Uri data) {
-        HashMap<String, Uri> results = new HashMap<>();
-        results.put(contentType, data);
-        // grant for the target app.
-        mController.grantInlineReplyUriPermission(mEntry.getSbn(), data);
-        Intent fillInIntent = new Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
-        RemoteInput.addDataResultToIntent(mRemoteInput, fillInIntent, results);
-
-        Bundle bundle = new Bundle();
-        bundle.putString(mRemoteInput.getResultKey(), mEditText.getText().toString());
-        RemoteInput.addResultsToIntent(mRemoteInputs, fillInIntent,
-                bundle);
-
-        CharSequence attachmentText =
-                mEntry.remoteInputAttachment.getClip().getDescription().getLabel();
-
-        CharSequence attachmentLabel = TextUtils.isEmpty(attachmentText)
-                ? mContext.getString(R.string.remote_input_image_insertion_text)
-                : attachmentText;
-        // add content description to reply text for context
-        CharSequence fullText = TextUtils.isEmpty(mEditText.getText())
-                ? attachmentLabel
-                : "\"" + attachmentLabel + "\" " + mEditText.getText();
-
-        mEntry.remoteInputText = fullText;
-
-        // mirror prepareRemoteInputFromText for text input
-        if (mEntry.editedSuggestionInfo == null) {
-            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT);
-        } else if (mEntry.remoteInputAttachment == null) {
-            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE);
-        }
-
-        return fillInIntent;
-    }
-
-    private void sendRemoteInput(Intent intent) {
-        if (mBouncerChecker != null && mBouncerChecker.showBouncerIfNecessary()) {
-            mEditText.hideIme();
-            for (OnSendRemoteInputListener listener : new ArrayList<>(mOnSendListeners)) {
-                listener.onSendRequestBounced();
-            }
-            return;
-        }
-
+    /** Show the "sending in-progress" UI. */
+    public void startSending() {
         mEditText.setEnabled(false);
         mSendButton.setVisibility(INVISIBLE);
         mProgressBar.setVisibility(VISIBLE);
-        mEntry.lastRemoteInputSent = SystemClock.elapsedRealtime();
-        mEntry.mRemoteEditImeAnimatingAway = true;
-        mController.addSpinning(mEntry.getKey(), mToken);
-        mController.removeRemoteInput(mEntry, mToken);
         mEditText.mShowImeOnInputConnection = false;
-        mController.remoteInputSent(mEntry);
-        mEntry.setHasSentReply();
+    }
 
-        for (OnSendRemoteInputListener listener : new ArrayList<>(mOnSendListeners)) {
-            listener.onSendRemoteInput();
+    private void sendRemoteInput() {
+        for (Runnable listener : new ArrayList<>(mOnSendListeners)) {
+            listener.run();
         }
-
-        // Tell ShortcutManager that this package has been "activated".  ShortcutManager
-        // will reset the throttling for this package.
-        // Strictly speaking, the intent receiver may be different from the notification publisher,
-        // but that's an edge case, and also because we can't always know which package will receive
-        // an intent, so we just reset for the publisher.
-        getContext().getSystemService(ShortcutManager.class).onApplicationActive(
-                mEntry.getSbn().getPackageName(),
-                mEntry.getSbn().getUser().getIdentifier());
-
-        mUiEventLogger.logWithInstanceId(
-                NotificationRemoteInputEvent.NOTIFICATION_REMOTE_INPUT_SEND,
-                mEntry.getSbn().getUid(), mEntry.getSbn().getPackageName(),
-                mEntry.getSbn().getInstanceId());
-        try {
-            mPendingIntent.send(mContext, 0, intent);
-        } catch (PendingIntent.CanceledException e) {
-            Log.i(TAG, "Unable to send remote input result", e);
-            mUiEventLogger.logWithInstanceId(
-                    NotificationRemoteInputEvent.NOTIFICATION_REMOTE_INPUT_FAILURE,
-                    mEntry.getSbn().getUid(), mEntry.getSbn().getPackageName(),
-                    mEntry.getSbn().getInstanceId());
-        }
-
-        setAttachment(null);
     }
 
     public CharSequence getText() {
@@ -478,7 +377,7 @@
     @Override
     public void onClick(View v) {
         if (v == mSendButton) {
-            sendRemoteInput(prepareRemoteInput());
+            sendRemoteInput();
         }
     }
 
@@ -687,55 +586,18 @@
         return mEditText.isFocused() && mEditText.isEnabled();
     }
 
+    // TODO(b/193539698): move this to the controller
     public void stealFocusFrom(RemoteInputView other) {
         other.close();
         setPendingIntent(other.mPendingIntent);
         setRemoteInput(other.mRemoteInputs, other.mRemoteInput, mEntry.editedSuggestionInfo);
         setRevealParameters(other.mRevealCx, other.mRevealCy, other.mRevealR);
+        getController().setPendingIntent(other.mPendingIntent);
+        getController().setRemoteInput(other.mRemoteInput);
+        getController().setRemoteInputs(other.mRemoteInputs);
         focus();
     }
 
-    /**
-     * Tries to find an action in {@param actions} that matches the current pending intent
-     * of this view and updates its state to that of the found action
-     *
-     * @return true if a matching action was found, false otherwise
-     */
-    public boolean updatePendingIntentFromActions(Notification.Action[] actions) {
-        if (mPendingIntent == null || actions == null) {
-            return false;
-        }
-        Intent current = mPendingIntent.getIntent();
-        if (current == null) {
-            return false;
-        }
-
-        for (Notification.Action a : actions) {
-            RemoteInput[] inputs = a.getRemoteInputs();
-            if (a.actionIntent == null || inputs == null) {
-                continue;
-            }
-            Intent candidate = a.actionIntent.getIntent();
-            if (!current.filterEquals(candidate)) {
-                continue;
-            }
-
-            RemoteInput input = null;
-            for (RemoteInput i : inputs) {
-                if (i.getAllowFreeFormInput()) {
-                    input = i;
-                }
-            }
-            if (input == null) {
-                continue;
-            }
-            setPendingIntent(a.actionIntent);
-            setRemoteInput(inputs, input, null /* editedSuggestionInfo*/);
-            return true;
-        }
-        return false;
-    }
-
     public PendingIntent getPendingIntent() {
         return mPendingIntent;
     }
@@ -814,16 +676,6 @@
         return getVisibility() == VISIBLE && mController.isSpinning(mEntry.getKey(), mToken);
     }
 
-    /**
-     * Sets a {@link com.android.systemui.statusbar.NotificationRemoteInputManager.BouncerChecker}
-     * that will be used to determine if the device needs to be unlocked before sending the
-     * RemoteInput.
-     */
-    public void setBouncerChecker(
-            @Nullable NotificationRemoteInputManager.BouncerChecker bouncerChecker) {
-        mBouncerChecker = bouncerChecker;
-    }
-
     /** Registers a listener for focus-change events on the EditText */
     public void addOnEditTextFocusChangedListener(View.OnFocusChangeListener listener) {
         mEditTextFocusChangeListeners.add(listener);
@@ -846,26 +698,15 @@
     }
 
     /** Registers a listener for send events on this RemoteInputView */
-    public void addOnSendRemoteInputListener(OnSendRemoteInputListener listener) {
+    public void addOnSendRemoteInputListener(Runnable listener) {
         mOnSendListeners.add(listener);
     }
 
     /** Removes a previously-added listener for send events on this RemoteInputView */
-    public void removeOnSendRemoteInputListener(OnSendRemoteInputListener listener) {
+    public void removeOnSendRemoteInputListener(Runnable listener) {
         mOnSendListeners.remove(listener);
     }
 
-    /** Listener for send events */
-    public interface OnSendRemoteInputListener {
-        /** Invoked when the remote input has been sent successfully. */
-        void onSendRemoteInput();
-        /**
-         * Invoked when the user had requested to send the remote input, but authentication was
-         * required and the bouncer was shown instead.
-         */
-        void onSendRequestBounced();
-    }
-
     /** Handler for button click on send action in IME. */
     private class EditorActionHandler implements TextView.OnEditorActionListener {
 
@@ -881,7 +722,7 @@
 
             if (isSoftImeEvent || isKeyboardEnterKey) {
                 if (mEditText.length() > 0 || mEntry.remoteInputAttachment != null) {
-                    sendRemoteInput(prepareRemoteInput());
+                    sendRemoteInput();
                 }
                 // Consume action to prevent IME from closing.
                 return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
index 383170e..ef0a5b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputViewController.kt
@@ -16,28 +16,101 @@
 
 package com.android.systemui.statusbar.policy
 
+import android.app.Notification
+import android.app.PendingIntent
+import android.app.RemoteInput
+import android.content.Intent
+import android.content.pm.ShortcutManager
+import android.net.Uri
+import android.os.Bundle
+import android.os.SystemClock
+import android.text.TextUtils
+import android.util.ArraySet
+import android.util.Log
 import android.view.View
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.R
+import com.android.systemui.statusbar.NotificationRemoteInputManager
+import com.android.systemui.statusbar.RemoteInputController
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.policy.RemoteInputView.NotificationRemoteInputEvent
 import com.android.systemui.statusbar.policy.dagger.RemoteInputViewScope
 import javax.inject.Inject
 
 interface RemoteInputViewController {
     fun bind()
     fun unbind()
+
+    /**
+     * A [NotificationRemoteInputManager.BouncerChecker] that will be used to determine if the
+     * device needs to be unlocked before sending the RemoteInput.
+     */
+    var bouncerChecker: NotificationRemoteInputManager.BouncerChecker?
+
+    // TODO(b/193539698): these properties probably shouldn't be nullable
+    /** A [PendingIntent] to be used to send the RemoteInput. */
+    var pendingIntent: PendingIntent?
+    /** The [RemoteInput] data backing this Controller. */
+    var remoteInput: RemoteInput?
+    /** Other [RemoteInput]s from the notification associated with this Controller. */
+    var remoteInputs: Array<RemoteInput>?
+
+    /**
+     * Tries to find an action in {@param actions} that matches the current pending intent
+     * of this view and updates its state to that of the found action
+     *
+     * @return true if a matching action was found, false otherwise
+     */
+    fun updatePendingIntentFromActions(actions: Array<Notification.Action>?): Boolean
+
+    /** Registers a listener for send events. */
+    fun addOnSendRemoteInputListener(listener: OnSendRemoteInputListener)
+
+    /** Unregisters a listener previously registered via [addOnSendRemoteInputListener] */
+    fun removeOnSendRemoteInputListener(listener: OnSendRemoteInputListener)
 }
 
+/** Listener for send events  */
+interface OnSendRemoteInputListener {
+
+    /** Invoked when the remote input has been sent successfully.  */
+    fun onSendRemoteInput()
+
+    /**
+     * Invoked when the user had requested to send the remote input, but authentication was
+     * required and the bouncer was shown instead.
+     */
+    fun onSendRequestBounced()
+}
+
+private const val TAG = "RemoteInput"
+
 @RemoteInputViewScope
 class RemoteInputViewControllerImpl @Inject constructor(
     private val view: RemoteInputView,
-    private val remoteInputQuickSettingsDisabler: RemoteInputQuickSettingsDisabler
+    private val entry: NotificationEntry,
+    private val remoteInputQuickSettingsDisabler: RemoteInputQuickSettingsDisabler,
+    private val remoteInputController: RemoteInputController,
+    private val shortcutManager: ShortcutManager,
+    private val uiEventLogger: UiEventLogger
 ) : RemoteInputViewController {
 
+    private val onSendListeners = ArraySet<OnSendRemoteInputListener>()
+    private val resources get() = view.resources
+
     private var isBound = false
 
+    override var pendingIntent: PendingIntent? = null
+    override var bouncerChecker: NotificationRemoteInputManager.BouncerChecker? = null
+    override var remoteInput: RemoteInput? = null
+    override var remoteInputs: Array<RemoteInput>? = null
+
     override fun bind() {
         if (isBound) return
         isBound = true
 
         view.addOnEditTextFocusChangedListener(onFocusChangeListener)
+        view.addOnSendRemoteInputListener(onSendRemoteInputListener)
     }
 
     override fun unbind() {
@@ -45,9 +118,159 @@
         isBound = false
 
         view.removeOnEditTextFocusChangedListener(onFocusChangeListener)
+        view.removeOnSendRemoteInputListener(onSendRemoteInputListener)
+    }
+
+    override fun updatePendingIntentFromActions(actions: Array<Notification.Action>?): Boolean {
+        actions ?: return false
+        val current: Intent = pendingIntent?.intent ?: return false
+        for (a in actions) {
+            val actionIntent = a.actionIntent ?: continue
+            val inputs = a.remoteInputs ?: continue
+            if (!current.filterEquals(actionIntent.intent)) continue
+            val input = inputs.firstOrNull { it.allowFreeFormInput } ?: continue
+            pendingIntent = actionIntent
+            remoteInput = input
+            remoteInputs = inputs
+            view.pendingIntent = actionIntent
+            view.setRemoteInput(inputs, input, null /* editedSuggestionInfo */)
+            return true
+        }
+        return false
+    }
+
+    override fun addOnSendRemoteInputListener(listener: OnSendRemoteInputListener) {
+        onSendListeners.add(listener)
+    }
+
+    /** Removes a previously-added listener for send events on this RemoteInputView  */
+    override fun removeOnSendRemoteInputListener(listener: OnSendRemoteInputListener) {
+        onSendListeners.remove(listener)
     }
 
     private val onFocusChangeListener = View.OnFocusChangeListener { _, hasFocus ->
         remoteInputQuickSettingsDisabler.setRemoteInputActive(hasFocus)
     }
-}
\ No newline at end of file
+
+    private val onSendRemoteInputListener = Runnable {
+        val remoteInput = remoteInput ?: run {
+            Log.e(TAG, "cannot send remote input, RemoteInput data is null")
+            return@Runnable
+        }
+        val pendingIntent = pendingIntent ?: run {
+            Log.e(TAG, "cannot send remote input, PendingIntent is null")
+            return@Runnable
+        }
+        val intent = prepareRemoteInput(remoteInput)
+        sendRemoteInput(pendingIntent, intent)
+    }
+
+    private fun sendRemoteInput(pendingIntent: PendingIntent, intent: Intent) {
+        if (bouncerChecker?.showBouncerIfNecessary() == true) {
+            view.hideIme()
+            for (listener in onSendListeners.toList()) {
+                listener.onSendRequestBounced()
+            }
+            return
+        }
+
+        view.startSending()
+
+        entry.lastRemoteInputSent = SystemClock.elapsedRealtime()
+        entry.mRemoteEditImeAnimatingAway = true
+        remoteInputController.addSpinning(entry.key, view.mToken)
+        remoteInputController.removeRemoteInput(entry, view.mToken)
+        remoteInputController.remoteInputSent(entry)
+        entry.setHasSentReply()
+
+        for (listener in onSendListeners.toList()) {
+            listener.onSendRemoteInput()
+        }
+
+        // Tell ShortcutManager that this package has been "activated". ShortcutManager will reset
+        // the throttling for this package.
+        // Strictly speaking, the intent receiver may be different from the notification publisher,
+        // but that's an edge case, and also because we can't always know which package will receive
+        // an intent, so we just reset for the publisher.
+        shortcutManager.onApplicationActive(entry.sbn.packageName, entry.sbn.user.identifier)
+
+        uiEventLogger.logWithInstanceId(
+                NotificationRemoteInputEvent.NOTIFICATION_REMOTE_INPUT_SEND,
+                entry.sbn.uid, entry.sbn.packageName,
+                entry.sbn.instanceId)
+
+        try {
+            pendingIntent.send(view.context, 0, intent)
+        } catch (e: PendingIntent.CanceledException) {
+            Log.i(TAG, "Unable to send remote input result", e)
+            uiEventLogger.logWithInstanceId(
+                    NotificationRemoteInputEvent.NOTIFICATION_REMOTE_INPUT_FAILURE,
+                    entry.sbn.uid, entry.sbn.packageName,
+                    entry.sbn.instanceId)
+        }
+
+        view.clearAttachment()
+    }
+
+    /**
+     * Reply intent
+     * @return returns intent with granted URI permissions that should be used immediately
+     */
+    private fun prepareRemoteInput(remoteInput: RemoteInput): Intent =
+            if (entry.remoteInputAttachment == null) prepareRemoteInputFromText(remoteInput)
+            else prepareRemoteInputFromData(
+                    remoteInput,
+                    entry.remoteInputMimeType,
+                    entry.remoteInputUri)
+
+    private fun prepareRemoteInputFromText(remoteInput: RemoteInput): Intent {
+        val results = Bundle()
+        results.putString(remoteInput.resultKey, view.text.toString())
+        val fillInIntent = Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+        RemoteInput.addResultsToIntent(remoteInputs, fillInIntent, results)
+        entry.remoteInputText = view.text
+        view.clearAttachment()
+        entry.remoteInputUri = null
+        entry.remoteInputMimeType = null
+        if (entry.editedSuggestionInfo == null) {
+            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT)
+        } else {
+            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE)
+        }
+        return fillInIntent
+    }
+
+    private fun prepareRemoteInputFromData(
+        remoteInput: RemoteInput,
+        contentType: String,
+        data: Uri
+    ): Intent {
+        val results = HashMap<String, Uri>()
+        results[contentType] = data
+        // grant for the target app.
+        remoteInputController.grantInlineReplyUriPermission(entry.sbn, data)
+        val fillInIntent = Intent().addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
+        RemoteInput.addDataResultToIntent(remoteInput, fillInIntent, results)
+        val bundle = Bundle()
+        bundle.putString(remoteInput.resultKey, view.text.toString())
+        RemoteInput.addResultsToIntent(remoteInputs, fillInIntent, bundle)
+        val attachmentText: CharSequence = entry.remoteInputAttachment.clip.description.label
+        val attachmentLabel =
+                if (TextUtils.isEmpty(attachmentText))
+                    resources.getString(R.string.remote_input_image_insertion_text)
+                else attachmentText
+        // add content description to reply text for context
+        val fullText =
+                if (TextUtils.isEmpty(view.text)) attachmentLabel
+                else "\"" + attachmentLabel + "\" " + view.text
+        entry.remoteInputText = fullText
+
+        // mirror prepareRemoteInputFromText for text input
+        if (entry.editedSuggestionInfo == null) {
+            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_FREE_FORM_INPUT)
+        } else if (entry.remoteInputAttachment == null) {
+            RemoteInput.setResultsSource(fillInIntent, RemoteInput.SOURCE_CHOICE)
+        }
+        return fillInIntent
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsController.kt
new file mode 100644
index 0000000..c6dbdb1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsController.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 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.policy
+
+/**
+ * Interface for tracking packages with running foreground services and demoting foreground status
+ */
+interface RunningFgsController : CallbackController<RunningFgsController.Callback> {
+
+    /**
+     * @return A list of [UserPackageTime]s which have running foreground service(s)
+     */
+    fun getPackagesWithFgs(): List<UserPackageTime>
+
+    /**
+     * Stops all foreground services running as a package
+     * @param userId the userId the package is running under
+     * @param packageName the packageName
+     */
+    fun stopFgs(userId: Int, packageName: String)
+
+    /**
+     * Returns when the list of packages with foreground services changes
+     */
+    interface Callback {
+        /**
+         * The thing that
+         * @param packages the list of packages
+         */
+        fun onFgsPackagesChanged(packages: List<UserPackageTime>)
+    }
+
+    /**
+     * A triplet <user, packageName, timeMillis> where each element is a package running
+     * under a user that has had at least one foreground service running since timeMillis.
+     * Time should be derived from [SystemClock.elapsedRealtime].
+     */
+    data class UserPackageTime(val userId: Int, val packageName: String, val startTimeMillis: Long)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsControllerImpl.kt
new file mode 100644
index 0000000..d44d365
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RunningFgsControllerImpl.kt
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2021 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.policy
+
+import android.app.IActivityManager
+import android.app.IForegroundServiceObserver
+import android.os.IBinder
+import android.os.RemoteException
+import android.util.Log
+import androidx.annotation.GuardedBy
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.LifecycleOwner
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.statusbar.policy.RunningFgsController.Callback
+import com.android.systemui.statusbar.policy.RunningFgsController.UserPackageTime
+import com.android.systemui.util.time.SystemClock
+import java.util.concurrent.Executor
+import javax.inject.Inject
+
+/**
+ * Implementation for [RunningFgsController]
+ */
+@SysUISingleton
+class RunningFgsControllerImpl @Inject constructor(
+    @Background private val executor: Executor,
+    private val systemClock: SystemClock,
+    private val activityManager: IActivityManager
+) : RunningFgsController, IForegroundServiceObserver.Stub() {
+
+    companion object {
+        private val LOG_TAG = RunningFgsControllerImpl::class.java.simpleName
+    }
+
+    private val lock = Any()
+
+    @GuardedBy("lock")
+    var initialized = false
+
+    @GuardedBy("lock")
+    private val runningServiceTokens = mutableMapOf<UserPackageKey, StartTimeAndTokensValue>()
+
+    @GuardedBy("lock")
+    private val callbacks = mutableSetOf<Callback>()
+
+    fun init() {
+        synchronized(lock) {
+            if (initialized) {
+                return
+            }
+            try {
+                activityManager.registerForegroundServiceObserver(this)
+            } catch (e: RemoteException) {
+                e.rethrowFromSystemServer()
+            }
+
+            initialized = true
+        }
+    }
+
+    override fun addCallback(listener: Callback) {
+        init()
+        synchronized(lock) { callbacks.add(listener) }
+    }
+
+    override fun removeCallback(listener: Callback) {
+        init()
+        synchronized(lock) {
+            if (!callbacks.remove(listener)) {
+                Log.e(LOG_TAG, "Callback was not registered.", RuntimeException())
+            }
+        }
+    }
+
+    override fun observe(lifecycle: Lifecycle?, listener: Callback?): Callback {
+        init()
+        return super.observe(lifecycle, listener)
+    }
+
+    override fun observe(owner: LifecycleOwner?, listener: Callback?): Callback {
+        init()
+        return super.observe(owner, listener)
+    }
+
+    override fun getPackagesWithFgs(): List<UserPackageTime> {
+        init()
+        return synchronized(lock) { getPackagesWithFgsLocked() }
+    }
+
+    private fun getPackagesWithFgsLocked(): List<UserPackageTime> =
+            runningServiceTokens.map {
+                UserPackageTime(it.key.userId, it.key.packageName, it.value.fgsStartTime)
+            }
+
+    override fun stopFgs(userId: Int, packageName: String) {
+        init()
+        try {
+            activityManager.makeServicesNonForeground(packageName, userId)
+        } catch (e: RemoteException) {
+            e.rethrowFromSystemServer()
+        }
+    }
+
+    private data class UserPackageKey(
+        val userId: Int,
+        val packageName: String
+    )
+
+    private class StartTimeAndTokensValue(systemClock: SystemClock) {
+        val fgsStartTime = systemClock.elapsedRealtime()
+        var tokens = mutableSetOf<IBinder>()
+        fun addToken(token: IBinder): Boolean {
+            return tokens.add(token)
+        }
+
+        fun removeToken(token: IBinder): Boolean {
+            return tokens.remove(token)
+        }
+
+        val isEmpty: Boolean
+            get() = tokens.isEmpty()
+    }
+
+    override fun onForegroundStateChanged(
+        token: IBinder,
+        packageName: String,
+        userId: Int,
+        isForeground: Boolean
+    ) {
+        val result = synchronized(lock) {
+            val userPackageKey = UserPackageKey(userId, packageName)
+            if (isForeground) {
+                var addedNew = false
+                runningServiceTokens.getOrPut(userPackageKey) {
+                    addedNew = true
+                    StartTimeAndTokensValue(systemClock)
+                }.addToken(token)
+                if (!addedNew) {
+                    return
+                }
+            } else {
+                val startTimeAndTokensValue = runningServiceTokens[userPackageKey]
+                if (startTimeAndTokensValue?.removeToken(token) == false) {
+                    Log.e(LOG_TAG,
+                            "Stopped foreground service was not known to be running.")
+                    return
+                }
+                if (!startTimeAndTokensValue!!.isEmpty) {
+                    return
+                }
+                runningServiceTokens.remove(userPackageKey)
+            }
+            getPackagesWithFgsLocked().toList()
+        }
+
+        callbacks.forEach { executor.execute { it.onFgsPackagesChanged(result) } }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
index 4e33529..a537b2a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SmartReplyView.java
@@ -1,7 +1,8 @@
 package com.android.systemui.statusbar.policy;
 
+import static java.lang.Float.NaN;
+
 import android.annotation.ColorInt;
-import android.annotation.NonNull;
 import android.app.Notification;
 import android.app.PendingIntent;
 import android.app.RemoteInput;
@@ -14,10 +15,12 @@
 import android.graphics.drawable.GradientDrawable;
 import android.graphics.drawable.InsetDrawable;
 import android.graphics.drawable.RippleDrawable;
+import android.os.SystemClock;
 import android.text.Layout;
 import android.text.TextPaint;
 import android.text.method.TransformationMethod;
 import android.util.AttributeSet;
+import android.util.IndentingPrintWriter;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -25,6 +28,8 @@
 import android.widget.Button;
 import android.widget.TextView;
 
+import androidx.annotation.NonNull;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ContrastColorUtil;
 import com.android.systemui.R;
@@ -89,6 +94,13 @@
     private int mMaxNumActions;
     private int mMinNumSystemGeneratedReplies;
 
+    // DEBUG variables tracked for the dump()
+    private long mLastDrawChildTime;
+    private long mLastDispatchDrawTime;
+    private long mLastMeasureTime;
+    private int mTotalSqueezeRemeasureAttempts;
+    private boolean mDidHideSystemReplies;
+
     public SmartReplyView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
@@ -207,6 +219,7 @@
     private void clearLayoutLineCount(View view) {
         if (view instanceof TextView) {
             ((TextView) view).nullLayouts();
+            view.forceLayout();
         }
     }
 
@@ -217,6 +230,7 @@
 
         // Mark all buttons as hidden and un-squeezed.
         resetButtonsLayoutParams();
+        mTotalSqueezeRemeasureAttempts = 0;
 
         if (!mCandidateButtonQueueForSqueezing.isEmpty()) {
             Log.wtf(TAG, "Single line button queue leaked between onMeasure calls");
@@ -251,18 +265,29 @@
             if (maxNumActions != -1 // -1 means 'no limit'
                     && lp.mButtonType == SmartButtonType.ACTION
                     && numShownActions >= maxNumActions) {
+                lp.mNoShowReason = "max-actions-shown";
                 // We've reached the maximum number of actions, don't add another one!
                 continue;
             }
 
             clearLayoutLineCount(child);
             child.measure(MEASURE_SPEC_ANY_LENGTH, heightMeasureSpec);
+            if (((Button) child).getLayout() == null) {
+                Log.wtf(TAG, "Button layout is null after measure.");
+            }
 
             coveredSuggestions.add(child);
 
             final int lineCount = ((Button) child).getLineCount();
-            if (lineCount < 1 || lineCount > 2) {
-                // If smart reply has no text, or more than two lines, then don't show it.
+            if (lineCount < 1) {
+                // If smart reply has no text, then don't show it.
+                lp.mNoShowReason = "line-count-0";
+                continue;
+
+            }
+            if (lineCount > 2) {
+                // If smart reply has more than two lines, then don't show it.
+                lp.mNoShowReason = "line-count-3+";
                 continue;
             }
 
@@ -311,6 +336,7 @@
                     markButtonsWithPendingSqueezeStatusAs(
                             LayoutParams.SQUEEZE_STATUS_FAILED, coveredSuggestions);
 
+                    lp.mNoShowReason = "overflow";
                     // The current button doesn't fit, keep on adding lower-priority buttons in case
                     // any of those fit.
                     continue;
@@ -323,22 +349,26 @@
             }
 
             lp.show = true;
+            lp.mNoShowReason = "n/a";
             displayedChildCount++;
             if (lp.mButtonType == SmartButtonType.ACTION) {
                 numShownActions++;
             }
         }
 
+        mDidHideSystemReplies = false;
         if (mSmartRepliesGeneratedByAssistant) {
             if (!gotEnoughSmartReplies(smartReplies)) {
                 // We don't have enough smart replies - hide all of them.
                 for (View smartReplyButton : smartReplies) {
                     final LayoutParams lp = (LayoutParams) smartReplyButton.getLayoutParams();
                     lp.show = false;
+                    lp.mNoShowReason = "not-enough-system-replies";
                 }
                 // Reset our measures back to when we had only added actions (before adding
                 // replies).
                 accumulatedMeasures = actionsMeasures;
+                mDidHideSystemReplies = true;
             }
         }
 
@@ -356,6 +386,7 @@
                                      accumulatedMeasures.mMeasuredWidth),
                             widthMeasureSpec),
                 resolveSize(buttonHeight, heightMeasureSpec));
+        mLastMeasureTime = SystemClock.elapsedRealtime();
     }
 
     // TODO: this should be replaced, and instead, setMinSystemGenerated... should be invoked
@@ -371,6 +402,55 @@
         }
     }
 
+    /** Dump internal state for debugging */
+    public void dump(IndentingPrintWriter pw) {
+        pw.println(this);
+        pw.increaseIndent();
+        pw.print("mMaxSqueezeRemeasureAttempts=");
+        pw.println(mMaxSqueezeRemeasureAttempts);
+        pw.print("mTotalSqueezeRemeasureAttempts=");
+        pw.println(mTotalSqueezeRemeasureAttempts);
+        pw.print("mMaxNumActions=");
+        pw.println(mMaxNumActions);
+        pw.print("mSmartRepliesGeneratedByAssistant=");
+        pw.println(mSmartRepliesGeneratedByAssistant);
+        pw.print("mMinNumSystemGeneratedReplies=");
+        pw.println(mMinNumSystemGeneratedReplies);
+        pw.print("mHeightUpperLimit=");
+        pw.println(mHeightUpperLimit);
+        pw.print("mDidHideSystemReplies=");
+        pw.println(mDidHideSystemReplies);
+        long now = SystemClock.elapsedRealtime();
+        pw.print("lastMeasureAge (s)=");
+        pw.println(mLastMeasureTime == 0 ? NaN : (now - mLastMeasureTime) / 1000.0f);
+        pw.print("lastDrawChildAge (s)=");
+        pw.println(mLastDrawChildTime == 0 ? NaN : (now - mLastDrawChildTime) / 1000.0f);
+        pw.print("lastDispatchDrawAge (s)=");
+        pw.println(mLastDispatchDrawTime == 0 ? NaN : (now - mLastDispatchDrawTime) / 1000.0f);
+        int numChildren = getChildCount();
+        pw.print("children: num=");
+        pw.println(numChildren);
+        pw.increaseIndent();
+        for (int i = 0; i < numChildren; i++) {
+            View child = getChildAt(i);
+            LayoutParams lp = (LayoutParams) child.getLayoutParams();
+            pw.print("[");
+            pw.print(i);
+            pw.print("] type=");
+            pw.print(lp.mButtonType);
+            pw.print(" squeezeStatus=");
+            pw.print(lp.squeezeStatus);
+            pw.print(" show=");
+            pw.print(lp.show);
+            pw.print(" noShowReason=");
+            pw.print(lp.mNoShowReason);
+            pw.print(" view=");
+            pw.println(child);
+        }
+        pw.decreaseIndent();
+        pw.decreaseIndent();
+    }
+
     /**
      * Fields we keep track of inside onMeasure() to correctly measure the SmartReplyView depending
      * on which suggestions are added.
@@ -393,8 +473,11 @@
      * Returns whether our notification contains at least N smart replies (or 0) where N is
      * determined by {@link SmartReplyConstants}.
      */
-    // TODO: we probably sholdn't make this deliberation in the View
     private boolean gotEnoughSmartReplies(List<View> smartReplies) {
+        if (mMinNumSystemGeneratedReplies <= 1) {
+            // Count is irrelevant, do not bother.
+            return true;
+        }
         int numShownReplies = 0;
         for (View smartReplyButton : smartReplies) {
             final LayoutParams lp = (LayoutParams) smartReplyButton.getLayoutParams();
@@ -432,6 +515,7 @@
             final LayoutParams lp = (LayoutParams) child.getLayoutParams();
             lp.show = false;
             lp.squeezeStatus = LayoutParams.SQUEEZE_STATUS_NONE;
+            lp.mNoShowReason = "reset";
         }
     }
 
@@ -474,6 +558,7 @@
             final boolean moveLeft = initialLeftTextWidth > initialRightTextWidth;
             final int maxSqueezeRemeasureAttempts = mMaxSqueezeRemeasureAttempts;
             for (int i = 0; i < maxSqueezeRemeasureAttempts; i++) {
+                mTotalSqueezeRemeasureAttempts++;
                 final int newPosition =
                         moveLeft ? mBreakIterator.previous() : mBreakIterator.next();
                 if (newPosition == BreakIterator.DONE) {
@@ -523,6 +608,9 @@
                 button.getPaddingLeft() + button.getPaddingRight() + textWidth
                       + getLeftCompoundDrawableWidthWithPadding(button), MeasureSpec.AT_MOST);
         button.measure(widthMeasureSpec, heightMeasureSpec);
+        if (button.getLayout() == null) {
+            Log.wtf(TAG, "Button layout is null after measure.");
+        }
 
         final int newWidth = button.getMeasuredWidth();
 
@@ -613,7 +701,17 @@
     @Override
     protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
         final LayoutParams lp = (LayoutParams) child.getLayoutParams();
-        return lp.show && super.drawChild(canvas, child, drawingTime);
+        if (!lp.show) {
+            return false;
+        }
+        mLastDrawChildTime = SystemClock.elapsedRealtime();
+        return super.drawChild(canvas, child, drawingTime);
+    }
+
+    @Override
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+        mLastDispatchDrawTime = SystemClock.elapsedRealtime();
     }
 
     /**
@@ -695,6 +793,7 @@
         private boolean show = false;
         private int squeezeStatus = SQUEEZE_STATUS_NONE;
         SmartButtonType mButtonType = SmartButtonType.REPLY;
+        String mNoShowReason = "new";
 
         private LayoutParams(Context c, AttributeSet attrs) {
             super(c, attrs);
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 0443d94..cdbdb23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -55,6 +55,8 @@
 import android.view.WindowManagerGlobal;
 import android.widget.BaseAdapter;
 
+import androidx.annotation.Nullable;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.logging.UiEventLogger;
@@ -77,6 +79,7 @@
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.qs.QSUserSwitcherEvent;
 import com.android.systemui.qs.tiles.UserDetailView;
+import com.android.systemui.qs.user.UserSwitchDialogController.DialogShower;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
@@ -348,7 +351,7 @@
                 boolean canCreateGuest = (currentUserCanCreateUsers || anyoneCanCreateUsers)
                         && guestRecord == null;
                 boolean canCreateUser = (currentUserCanCreateUsers || anyoneCanCreateUsers)
-                        && mUserManager.canAddMoreUsers();
+                        && mUserManager.canAddMoreUsers(UserManager.USER_TYPE_FULL_SECONDARY);
                 boolean createIsRestricted = !addUsersWhenLocked;
 
                 if (guestRecord == null) {
@@ -460,7 +463,7 @@
     }
 
     @VisibleForTesting
-    void onUserListItemClicked(UserRecord record) {
+    void onUserListItemClicked(UserRecord record, DialogShower dialogShower) {
         int id;
         if (record.isGuest && record.info == null) {
             // No guest user. Create one.
@@ -472,7 +475,7 @@
             mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_ADD);
             id = guestId;
         } else if (record.isAddUser) {
-            showAddUserDialog();
+            showAddUserDialog(dialogShower);
             return;
         } else {
             id = record.info.id;
@@ -481,7 +484,7 @@
         int currUserId = mUserTracker.getUserId();
         if (currUserId == id) {
             if (record.isGuest) {
-                showExitGuestDialog(id);
+                showExitGuestDialog(id, dialogShower);
             }
             return;
         }
@@ -490,11 +493,15 @@
             // If switching from guest, we want to bring up the guest exit dialog instead of switching
             UserInfo currUserInfo = mUserManager.getUserInfo(currUserId);
             if (currUserInfo != null && currUserInfo.isGuest()) {
-                showExitGuestDialog(currUserId, record.resolveId());
+                showExitGuestDialog(currUserId, record.resolveId(), dialogShower);
                 return;
             }
         }
-
+        if (dialogShower != null) {
+            // If we haven't morphed into another dialog, it means we have just switched users.
+            // Then, dismiss the dialog.
+            dialogShower.dismiss();
+        }
         switchToUserId(id);
     }
 
@@ -511,7 +518,7 @@
         }
     }
 
-    protected void showExitGuestDialog(int id) {
+    private void showExitGuestDialog(int id, DialogShower dialogShower) {
         int newId = UserHandle.USER_SYSTEM;
         if (mResumeUserOnGuestLogout && mLastNonGuestUser != UserHandle.USER_SYSTEM) {
             UserInfo info = mUserManager.getUserInfo(mLastNonGuestUser);
@@ -519,23 +526,31 @@
                 newId = info.id;
             }
         }
-        showExitGuestDialog(id, newId);
+        showExitGuestDialog(id, newId, dialogShower);
     }
 
-    protected void showExitGuestDialog(int id, int targetId) {
+    private void showExitGuestDialog(int id, int targetId, DialogShower dialogShower) {
         if (mExitGuestDialog != null && mExitGuestDialog.isShowing()) {
             mExitGuestDialog.cancel();
         }
         mExitGuestDialog = new ExitGuestDialog(mContext, id, targetId);
-        mExitGuestDialog.show();
+        if (dialogShower != null) {
+            dialogShower.showDialog(mExitGuestDialog);
+        } else {
+            mExitGuestDialog.show();
+        }
     }
 
-    public void showAddUserDialog() {
+    private void showAddUserDialog(DialogShower dialogShower) {
         if (mAddUserDialog != null && mAddUserDialog.isShowing()) {
             mAddUserDialog.cancel();
         }
         mAddUserDialog = new AddUserDialog(mContext);
-        mAddUserDialog.show();
+        if (dialogShower != null) {
+            dialogShower.showDialog(mAddUserDialog);
+        } else {
+            mAddUserDialog.show();
+        }
     }
 
     private void listenForCallState() {
@@ -868,9 +883,17 @@
 
         /**
          * It handles click events on user list items.
+         *
+         * If the user switcher is hosted in a dialog, passing a non-null {@link DialogShower}
+         * will allow animation to and from the parent dialog.
+         *
          */
+        public void onUserListItemClicked(UserRecord record, @Nullable DialogShower dialogShower) {
+            mController.onUserListItemClicked(record, dialogShower);
+        }
+
         public void onUserListItemClicked(UserRecord record) {
-            mController.onUserListItemClicked(record);
+            onUserListItemClicked(record, null);
         }
 
         public String getName(Context context, UserRecord item) {
@@ -1156,7 +1179,7 @@
                 cancel();
             } else {
                 mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE);
-                dismiss();
+                dismissStack();
                 removeGuestUser(mGuestId, mTargetId);
             }
         }
@@ -1187,7 +1210,7 @@
             if (which == BUTTON_NEGATIVE) {
                 cancel();
             } else {
-                dismiss();
+                dismissStack();
                 if (ActivityManager.isUserAMonkey()) {
                     return;
                 }
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 5acce7f..b5ee62d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -45,9 +45,10 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.qs.GlobalSetting;
+import com.android.systemui.qs.SettingObserver;
 import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.util.Utils;
+import com.android.systemui.util.settings.GlobalSettings;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -66,8 +67,8 @@
     private final ArrayList<Callback> mCallbacks = new ArrayList<>();
     private final Object mCallbacksLock = new Object();
     private final Context mContext;
-    private final GlobalSetting mModeSetting;
-    private final GlobalSetting mConfigSetting;
+    private final SettingObserver mModeSetting;
+    private final SettingObserver mConfigSetting;
     private final NotificationManager mNoMan;
     private final AlarmManager mAlarmManager;
     private final SetupObserver mSetupObserver;
@@ -85,19 +86,20 @@
             Context context,
             @Main Handler handler,
             BroadcastDispatcher broadcastDispatcher,
-            DumpManager dumpManager) {
+            DumpManager dumpManager,
+            GlobalSettings globalSettings) {
         super(broadcastDispatcher);
         mContext = context;
-        mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
+        mModeSetting = new SettingObserver(globalSettings, handler, Global.ZEN_MODE) {
             @Override
-            protected void handleValueChanged(int value) {
+            protected void handleValueChanged(int value, boolean observedChange) {
                 updateZenMode(value);
                 fireZenChanged(value);
             }
         };
-        mConfigSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE_CONFIG_ETAG) {
+        mConfigSetting = new SettingObserver(globalSettings, handler, Global.ZEN_MODE_CONFIG_ETAG) {
             @Override
-            protected void handleValueChanged(int value) {
+            protected void handleValueChanged(int value, boolean observedChange) {
                 updateZenModeConfig();
             }
         };
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt
index aff39ef..d4abc40 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/dagger/RemoteInput.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.policy.dagger
 
+import com.android.systemui.statusbar.RemoteInputController
 import com.android.systemui.statusbar.policy.RemoteInputView
 import com.android.systemui.statusbar.policy.RemoteInputViewController
 import com.android.systemui.statusbar.policy.RemoteInputViewControllerImpl
@@ -32,7 +33,10 @@
 
     @Subcomponent.Factory
     interface Factory {
-        fun create(@BindsInstance view: RemoteInputView): RemoteInputViewSubcomponent
+        fun create(
+            @BindsInstance view: RemoteInputView,
+            @BindsInstance remoteInputController: RemoteInputController
+        ): RemoteInputViewSubcomponent
     }
 }
 
@@ -44,4 +48,4 @@
 
 @Qualifier
 @Retention(AnnotationRetention.BINARY)
-internal annotation class RemoteInputViewScope
\ No newline at end of file
+internal annotation class RemoteInputViewScope
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 6d176a7..39544fb 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -61,6 +61,7 @@
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.monet.ColorScheme;
 import com.android.systemui.settings.UserTracker;
@@ -176,6 +177,34 @@
                 ? WallpaperManager.FLAG_LOCK : WallpaperManager.FLAG_SYSTEM;
     }
 
+    private boolean isSeedColorSet(JSONObject jsonObject, WallpaperColors newWallpaperColors) {
+        if (newWallpaperColors == null) {
+            return false;
+        }
+        // Gets the color that was overridden in the theme setting if any.
+        String sysPaletteColor = (String) jsonObject.opt(OVERLAY_CATEGORY_SYSTEM_PALETTE);
+        if (sysPaletteColor == null) {
+            return false;
+        }
+        if (!sysPaletteColor.startsWith("#")) {
+            sysPaletteColor = "#" + sysPaletteColor;
+        }
+        final int systemPaletteColorArgb = Color.parseColor(sysPaletteColor);
+        // Gets seed colors from incoming {@link WallpaperColors} instance.
+        List<Integer> seedColors = ColorScheme.getSeedColors(newWallpaperColors);
+        for (int seedColor : seedColors) {
+            // The seed color from incoming {@link WallpaperColors} instance
+            // was set as color override.
+            if (seedColor == systemPaletteColorArgb) {
+                if (DEBUG) {
+                    Log.d(TAG, "Same as previous set system palette: " + sysPaletteColor);
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
     private void handleWallpaperColors(WallpaperColors wallpaperColors, int flags) {
         final boolean hadWallpaperColors = mCurrentColors != null;
         int latestWallpaperType = getLatestWallpaperType();
@@ -213,8 +242,11 @@
         try {
             JSONObject jsonObject = (overlayPackageJson == null) ? new JSONObject()
                     : new JSONObject(overlayPackageJson);
+            // The latest applied wallpaper should be the source of system colors when:
+            // There is not preset color applied and the incoming wallpaper color is not applied
             if (!COLOR_SOURCE_PRESET.equals(jsonObject.optString(OVERLAY_COLOR_SOURCE))
-                    && ((flags & latestWallpaperType) != 0)) {
+                    && ((flags & latestWallpaperType) != 0 && !isSeedColorSet(jsonObject,
+                    wallpaperColors))) {
                 mSkipSettingChange = true;
                 if (jsonObject.has(OVERLAY_CATEGORY_ACCENT_COLOR) || jsonObject.has(
                         OVERLAY_CATEGORY_SYSTEM_PALETTE)) {
@@ -280,7 +312,7 @@
             WakefulnessLifecycle wakefulnessLifecycle) {
         super(context);
 
-        mIsMonetEnabled = featureFlags.isMonetEnabled();
+        mIsMonetEnabled = featureFlags.isEnabled(Flags.MONET);
         mDeviceProvisionedController = deviceProvisionedController;
         mBroadcastDispatcher = broadcastDispatcher;
         mUserManager = userManager;
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
index cebc931..cd3e2d3 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
@@ -100,11 +100,11 @@
     fun provideShellProgressProvider(
         config: UnfoldTransitionConfig,
         provider: Optional<UnfoldTransitionProgressProvider>
-    ): Optional<ShellUnfoldProgressProvider> =
+    ): ShellUnfoldProgressProvider =
         if (config.isEnabled && provider.isPresent()) {
-            Optional.of(UnfoldProgressProvider(provider.get()))
+            UnfoldProgressProvider(provider.get())
         } else {
-            Optional.empty()
+            ShellUnfoldProgressProvider.NO_PROVIDER
         }
 }
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt b/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
index 9f33c27..f952476 100644
--- a/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/DumpUtils.kt
@@ -19,39 +19,15 @@
 import android.util.IndentingPrintWriter
 import android.view.View
 import java.io.PrintWriter
-import java.util.function.Consumer
 
 /**
- * Run some code that will print to an [IndentingPrintWriter] that wraps the given [PrintWriter].
+ * Get an [IndentingPrintWriter] which either is or wraps the given [PrintWriter].
  *
- * If the given [PrintWriter] is an [IndentingPrintWriter], the block will be passed that same
- * instance with [IndentingPrintWriter.increaseIndent] having been called, and calling
- * [IndentingPrintWriter.decreaseIndent] after completion of the block, so the passed [PrintWriter]
- * should not be used before the block completes.
+ * The original [PrintWriter] should not be used until the returned [IndentingPrintWriter] is no
+ * longer being used, to avoid inconsistent writing.
  */
-inline fun PrintWriter.withIndenting(block: (IndentingPrintWriter) -> Unit) {
-    if (this is IndentingPrintWriter) {
-        this.withIncreasedIndent { block(this) }
-    } else {
-        block(IndentingPrintWriter(this))
-    }
-}
-
-/**
- * Run some code that will print to an [IndentingPrintWriter] that wraps the given [PrintWriter].
- *
- * If the given [PrintWriter] is an [IndentingPrintWriter], the block will be passed that same
- * instance with [IndentingPrintWriter.increaseIndent] having been called, and calling
- * [IndentingPrintWriter.decreaseIndent] after completion of the block, so the passed [PrintWriter]
- * should not be used before the block completes.
- */
-fun PrintWriter.withIndenting(consumer: Consumer<IndentingPrintWriter>) {
-    if (this is IndentingPrintWriter) {
-        this.withIncreasedIndent { consumer.accept(this) }
-    } else {
-        consumer.accept(IndentingPrintWriter(this))
-    }
-}
+fun PrintWriter.asIndenting(): IndentingPrintWriter =
+    (this as? IndentingPrintWriter) ?: IndentingPrintWriter(this)
 
 /**
  * Run some code inside a block, with [IndentingPrintWriter.increaseIndent] having been called on
@@ -66,6 +42,19 @@
     }
 }
 
+/**
+ * Run some code inside a block, with [IndentingPrintWriter.increaseIndent] having been called on
+ * the given argument, and calling [IndentingPrintWriter.decreaseIndent] after completion.
+ */
+fun IndentingPrintWriter.withIncreasedIndent(runnable: Runnable) {
+    this.increaseIndent()
+    try {
+        runnable.run()
+    } finally {
+        this.decreaseIndent()
+    }
+}
+
 /** Return a readable string for the visibility */
 fun visibilityString(@View.Visibility visibility: Int): String = when (visibility) {
     View.GONE -> "gone"
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
index 4aad9b6..e8f6de7 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java
@@ -60,12 +60,12 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationChannelHelper;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -141,7 +141,7 @@
             NotificationEntryManager entryManager,
             NotifPipeline notifPipeline,
             SysUiState sysUiState,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             DumpManager dumpManager,
             Executor sysuiMainExecutor) {
         if (bubblesOptional.isPresent()) {
@@ -150,7 +150,7 @@
                     configurationController, statusBarService, notificationManager,
                     visibilityProvider,
                     interruptionStateProvider, zenModeController, notifUserManager,
-                    groupManager, entryManager, notifPipeline, sysUiState, featureFlags,
+                    groupManager, entryManager, notifPipeline, sysUiState, notifPipelineFlags,
                     dumpManager, sysuiMainExecutor);
         } else {
             return null;
@@ -174,7 +174,7 @@
             NotificationEntryManager entryManager,
             NotifPipeline notifPipeline,
             SysUiState sysUiState,
-            FeatureFlags featureFlags,
+            NotifPipelineFlags notifPipelineFlags,
             DumpManager dumpManager,
             Executor sysuiMainExecutor) {
         mContext = context;
@@ -194,7 +194,7 @@
                 ServiceManager.getService(Context.STATUS_BAR_SERVICE))
                 : statusBarService;
 
-        if (featureFlags.isNewNotifPipelineRenderingEnabled()) {
+        if (notifPipelineFlags.isNewPipelineEnabled()) {
             setupNotifPipeline();
         } else {
             setupNEM();
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
index 66c70ed..63ca94c 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShell.java
@@ -65,6 +65,7 @@
 import com.android.wm.shell.onehanded.OneHandedUiEventLogger;
 import com.android.wm.shell.pip.Pip;
 import com.android.wm.shell.protolog.ShellProtoLogImpl;
+import com.android.wm.shell.sizecompatui.SizeCompatUI;
 import com.android.wm.shell.splitscreen.SplitScreen;
 
 import java.io.FileDescriptor;
@@ -112,6 +113,7 @@
     private final Optional<OneHanded> mOneHandedOptional;
     private final Optional<HideDisplayCutout> mHideDisplayCutoutOptional;
     private final Optional<ShellCommandHandler> mShellCommandHandler;
+    private final Optional<SizeCompatUI> mSizeCompatUIOptional;
 
     private final CommandQueue mCommandQueue;
     private final ConfigurationController mConfigurationController;
@@ -128,6 +130,7 @@
     private KeyguardUpdateMonitorCallback mSplitScreenKeyguardCallback;
     private KeyguardUpdateMonitorCallback mPipKeyguardCallback;
     private KeyguardUpdateMonitorCallback mOneHandedKeyguardCallback;
+    private KeyguardUpdateMonitorCallback mSizeCompatUIKeyguardCallback;
     private WakefulnessLifecycle.Observer mWakefulnessObserver;
 
     @Inject
@@ -138,6 +141,7 @@
             Optional<OneHanded> oneHandedOptional,
             Optional<HideDisplayCutout> hideDisplayCutoutOptional,
             Optional<ShellCommandHandler> shellCommandHandler,
+            Optional<SizeCompatUI> sizeCompatUIOptional,
             CommandQueue commandQueue,
             ConfigurationController configurationController,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -162,6 +166,7 @@
         mWakefulnessLifecycle = wakefulnessLifecycle;
         mProtoTracer = protoTracer;
         mShellCommandHandler = shellCommandHandler;
+        mSizeCompatUIOptional = sizeCompatUIOptional;
         mSysUiMainExecutor = sysUiMainExecutor;
     }
 
@@ -176,6 +181,7 @@
         mSplitScreenOptional.ifPresent(this::initSplitScreen);
         mOneHandedOptional.ifPresent(this::initOneHanded);
         mHideDisplayCutoutOptional.ifPresent(this::initHideDisplayCutout);
+        mSizeCompatUIOptional.ifPresent(this::initSizeCompatUi);
     }
 
     @VisibleForTesting
@@ -254,6 +260,18 @@
             }
         };
         mKeyguardUpdateMonitor.registerCallback(mSplitScreenKeyguardCallback);
+
+        mWakefulnessLifecycle.addObserver(new WakefulnessLifecycle.Observer() {
+            @Override
+            public void onFinishedWakingUp() {
+                splitScreen.onFinishedWakingUp();
+            }
+
+            @Override
+            public void onFinishedGoingToSleep() {
+                splitScreen.onFinishedGoingToSleep();
+            }
+        });
     }
 
     @VisibleForTesting
@@ -367,6 +385,17 @@
         });
     }
 
+    @VisibleForTesting
+    void initSizeCompatUi(SizeCompatUI sizeCompatUI) {
+        mSizeCompatUIKeyguardCallback = new KeyguardUpdateMonitorCallback() {
+            @Override
+            public void onKeyguardOccludedChanged(boolean occluded) {
+                sizeCompatUI.onKeyguardOccludedChanged(occluded);
+            }
+        };
+        mKeyguardUpdateMonitor.registerCallback(mSizeCompatUIKeyguardCallback);
+    }
+
     @Override
     public void writeToProto(SystemUiTraceProto proto) {
         if (proto.wmShell == null) {
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index 5e0f427..e967033 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -18,14 +18,19 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
 import android.view.View;
 import android.widget.FrameLayout;
@@ -50,6 +55,9 @@
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.NotificationIconContainer;
 import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.util.time.FakeSystemClock;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -104,11 +112,14 @@
     private AnimatableClockView mLargeClockView;
     @Mock
     private FrameLayout mLargeClockFrame;
+    @Mock
+    private SecureSettings mSecureSettings;
 
     private final View mFakeSmartspaceView = new View(mContext);
 
     private KeyguardClockSwitchController mController;
     private View mSliceView;
+    private FakeExecutor mExecutor;
 
     @Before
     public void setup() {
@@ -129,6 +140,7 @@
 
         when(mView.isAttachedToWindow()).thenReturn(true);
         when(mSmartspaceController.buildAndConnectView(any())).thenReturn(mFakeSmartspaceView);
+        mExecutor = new FakeExecutor(new FakeSystemClock());
         mController = new KeyguardClockSwitchController(
                 mView,
                 mStatusBarStateController,
@@ -143,6 +155,8 @@
                 mSmartspaceController,
                 mKeyguardUnlockAnimationController,
                 mSmartSpaceTransitionController,
+                mSecureSettings,
+                mExecutor,
                 mResources
         );
 
@@ -194,7 +208,6 @@
         verifyAttachment(times(1));
 
         listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
-        verify(mView).onViewDetached();
         verify(mColorExtractor).removeOnColorsChangedListener(
                 any(ColorExtractor.OnColorsChangedListener.class));
     }
@@ -235,6 +248,25 @@
         verify(mSmartspaceController).requestSmartspaceUpdate();
     }
 
+    @Test
+    public void testChangeToDoubleLineClockSetsSmallClock() {
+        when(mSecureSettings.getInt(Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, 1))
+                .thenReturn(0);
+        ArgumentCaptor<ContentObserver> observerCaptor =
+                ArgumentCaptor.forClass(ContentObserver.class);
+        mController.init();
+        verify(mSecureSettings).registerContentObserver(any(Uri.class),
+                anyBoolean(), observerCaptor.capture());
+        ContentObserver observer = observerCaptor.getValue();
+        mExecutor.runAllReady();
+
+        // When a settings change has occurred to the small clock, make sure the view is adjusted
+        reset(mView);
+        observer.onChange(true);
+        mExecutor.runAllReady();
+        verify(mView).switchToClock(KeyguardClockSwitch.SMALL);
+    }
+
     private void verifyAttachment(VerificationMode times) {
         verify(mClockManager, times).addOnClockChangedListener(
                 any(ClockManager.ClockChangedListener.class));
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
index 6f2c565..ac1a83c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardHostViewControllerTest.java
@@ -80,8 +80,6 @@
         // Explicitly disable one handed keyguard.
         mTestableResources.addOverride(
                 R.bool.can_use_one_handed_bouncer, false);
-        mTestableResources.addOverride(
-                com.android.internal.R.bool.config_enableDynamicKeyguardPositioning, false);
 
         when(mKeyguardSecurityContainerControllerFactory.create(any(
                 KeyguardSecurityContainer.SecurityCallback.class)))
@@ -149,8 +147,6 @@
         // Start disabled.
         mTestableResources.addOverride(
                 R.bool.can_use_one_handed_bouncer, false);
-        mTestableResources.addOverride(
-                com.android.internal.R.bool.config_enableDynamicKeyguardPositioning, false);
 
         mKeyguardHostViewController.init();
         assertEquals(
@@ -160,8 +156,6 @@
         // And enable
         mTestableResources.addOverride(
                 R.bool.can_use_one_handed_bouncer, true);
-        mTestableResources.addOverride(
-                com.android.internal.R.bool.config_enableDynamicKeyguardPositioning, true);
 
         mKeyguardHostViewController.updateResources();
         assertEquals(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
index db87c5d..4bdab76 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt
@@ -75,8 +75,7 @@
     shouldListenForFingerprintAssistant = false,
     switchingUser = false,
     udfps = false,
-    userDoesNotHaveTrust = false,
-    userNeedsStrongAuth = false
+    userDoesNotHaveTrust = false
 )
 
 private fun faceModel(user: Int) = KeyguardFaceListenModel(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index 64bdc2e..030464a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -18,8 +18,10 @@
 
 import static android.view.WindowInsets.Type.ime;
 
+import static com.android.keyguard.KeyguardSecurityContainer.MODE_DEFAULT;
+import static com.android.keyguard.KeyguardSecurityContainer.MODE_ONE_HANDED;
+
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.ArgumentMatchers.eq;
@@ -27,7 +29,6 @@
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -49,6 +50,7 @@
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.settings.GlobalSettings;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -107,6 +109,8 @@
     private Resources mResources;
     @Mock
     private FalsingCollector mFalsingCollector;
+    @Mock
+    private GlobalSettings mGlobalSettings;
     private Configuration mConfiguration;
 
     private KeyguardSecurityContainerController mKeyguardSecurityContainerController;
@@ -140,7 +144,7 @@
                 mView, mAdminSecondaryLockScreenControllerFactory, mLockPatternUtils,
                 mKeyguardUpdateMonitor, mKeyguardSecurityModel, mMetricsLogger, mUiEventLogger,
                 mKeyguardStateController, mKeyguardSecurityViewFlipperController,
-                mConfigurationController, mFalsingCollector)
+                mConfigurationController, mFalsingCollector, mGlobalSettings)
                 .create(mSecurityCallback);
     }
 
@@ -178,30 +182,13 @@
     public void onResourcesUpdate_callsThroughOnRotationChange() {
         // Rotation is the same, shouldn't cause an update
         mKeyguardSecurityContainerController.updateResources();
-        verify(mView, times(0)).setOneHandedMode(anyBoolean());
+        verify(mView, never()).initMode(MODE_DEFAULT, mGlobalSettings);
 
         // Update rotation. Should trigger update
         mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE;
 
         mKeyguardSecurityContainerController.updateResources();
-        verify(mView, times(1)).setOneHandedMode(anyBoolean());
-    }
-
-    @Test
-    public void updateKeyguardPosition_callsThroughToViewInOneHandedMode() {
-        when(mView.isOneHandedMode()).thenReturn(true);
-        mKeyguardSecurityContainerController.updateKeyguardPosition(VIEW_WIDTH / 3f);
-        verify(mView).setOneHandedModeLeftAligned(true, false);
-
-        mKeyguardSecurityContainerController.updateKeyguardPosition((VIEW_WIDTH / 3f) * 2);
-        verify(mView).setOneHandedModeLeftAligned(false, false);
-    }
-
-    @Test
-    public void updateKeyguardPosition_ignoredInTwoHandedMode() {
-        when(mView.isOneHandedMode()).thenReturn(false);
-        mKeyguardSecurityContainerController.updateKeyguardPosition(1.0f);
-        verify(mView, never()).setOneHandedModeLeftAligned(anyBoolean(), anyBoolean());
+        verify(mView).initMode(MODE_DEFAULT, mGlobalSettings);
     }
 
     private void touchDownLeftSide() {
@@ -228,7 +215,7 @@
 
     @Test
     public void onInterceptTap_inhibitsFalsingInOneHandedMode() {
-        when(mView.isOneHandedMode()).thenReturn(true);
+        when(mView.getMode()).thenReturn(MODE_ONE_HANDED);
         when(mView.isOneHandedModeLeftAligned()).thenReturn(true);
 
         touchDownLeftSide();
@@ -251,83 +238,35 @@
     }
 
     @Test
-    public void showSecurityScreen_oneHandedMode_bothFlagsDisabled_noOneHandedMode() {
-        setUpKeyguardFlags(
-                /* deviceConfigCanUseOneHandedKeyguard= */false,
-                /* sysuiResourceCanUseOneHandedKeyguard= */false);
-
+    public void showSecurityScreen_oneHandedMode_flagDisabled_noOneHandedMode() {
+        when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(false);
         when(mKeyguardSecurityViewFlipperController.getSecurityView(
                 eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
                 .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
 
         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Pattern);
-        verify(mView).setOneHandedMode(false);
+        verify(mView).initMode(MODE_DEFAULT, mGlobalSettings);
     }
 
     @Test
-    public void showSecurityScreen_oneHandedMode_deviceFlagDisabled_noOneHandedMode() {
-        setUpKeyguardFlags(
-                /* deviceConfigCanUseOneHandedKeyguard= */false,
-                /* sysuiResourceCanUseOneHandedKeyguard= */true);
-
+    public void showSecurityScreen_oneHandedMode_flagEnabled_oneHandedMode() {
+        when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true);
         when(mKeyguardSecurityViewFlipperController.getSecurityView(
                 eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
                 .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
 
         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Pattern);
-        verify(mView).setOneHandedMode(false);
+        verify(mView).initMode(MODE_ONE_HANDED, mGlobalSettings);
     }
 
     @Test
-    public void showSecurityScreen_oneHandedMode_sysUiFlagDisabled_noOneHandedMode() {
-        setUpKeyguardFlags(
-                /* deviceConfigCanUseOneHandedKeyguard= */true,
-                /* sysuiResourceCanUseOneHandedKeyguard= */false);
-
-        when(mKeyguardSecurityViewFlipperController.getSecurityView(
-                eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
-                .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
-
-        mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Pattern);
-        verify(mView).setOneHandedMode(false);
-    }
-
-    @Test
-    public void showSecurityScreen_oneHandedMode_bothFlagsEnabled_oneHandedMode() {
-        setUpKeyguardFlags(
-                /* deviceConfigCanUseOneHandedKeyguard= */true,
-                /* sysuiResourceCanUseOneHandedKeyguard= */true);
-
-        when(mKeyguardSecurityViewFlipperController.getSecurityView(
-                eq(SecurityMode.Pattern), any(KeyguardSecurityCallback.class)))
-                .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
-
-        mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Pattern);
-        verify(mView).setOneHandedMode(true);
-    }
-
-    @Test
-    public void showSecurityScreen_twoHandedMode_bothFlagsEnabled_noOneHandedMode() {
-        setUpKeyguardFlags(
-                /* deviceConfigCanUseOneHandedKeyguard= */true,
-                /* sysuiResourceCanUseOneHandedKeyguard= */true);
-
+    public void showSecurityScreen_twoHandedMode_flagEnabled_noOneHandedMode() {
+        when(mResources.getBoolean(R.bool.can_use_one_handed_bouncer)).thenReturn(true);
         when(mKeyguardSecurityViewFlipperController.getSecurityView(
                 eq(SecurityMode.Password), any(KeyguardSecurityCallback.class)))
                 .thenReturn((KeyguardInputViewController) mKeyguardPasswordViewController);
 
         mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.Password);
-        verify(mView).setOneHandedMode(false);
-    }
-
-    private void setUpKeyguardFlags(
-            boolean deviceConfigCanUseOneHandedKeyguard,
-            boolean sysuiResourceCanUseOneHandedKeyguard) {
-        when(mResources.getBoolean(
-                com.android.internal.R.bool.config_enableDynamicKeyguardPositioning))
-                .thenReturn(deviceConfigCanUseOneHandedKeyguard);
-        when(mResources.getBoolean(
-                R.bool.can_use_one_handed_bouncer))
-                .thenReturn(sysuiResourceCanUseOneHandedKeyguard);
+        verify(mView).initMode(MODE_DEFAULT, mGlobalSettings);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 2efd369..c751081 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -19,6 +19,9 @@
 import static android.view.WindowInsets.Type.ime;
 import static android.view.WindowInsets.Type.systemBars;
 
+import static com.android.keyguard.KeyguardSecurityContainer.MODE_DEFAULT;
+import static com.android.keyguard.KeyguardSecurityContainer.MODE_ONE_HANDED;
+
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -37,6 +40,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.settings.GlobalSettings;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -59,9 +63,10 @@
 
     @Mock
     private WindowInsetsController mWindowInsetsController;
-
     @Mock
     private KeyguardSecurityViewFlipper mSecurityViewFlipper;
+    @Mock
+    private GlobalSettings mGlobalSettings;
 
     private KeyguardSecurityContainer mKeyguardSecurityContainer;
 
@@ -83,7 +88,7 @@
 
     @Test
     public void onMeasure_usesHalfWidthWithOneHandedModeEnabled() {
-        mKeyguardSecurityContainer.setOneHandedMode(/* oneHandedMode= */true);
+        mKeyguardSecurityContainer.initMode(MODE_ONE_HANDED, mGlobalSettings);
 
         int halfWidthMeasureSpec =
                 View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH / 2, View.MeasureSpec.EXACTLY);
@@ -94,7 +99,7 @@
 
     @Test
     public void onMeasure_usesFullWidthWithOneHandedModeDisabled() {
-        mKeyguardSecurityContainer.setOneHandedMode(/* oneHandedMode= */false);
+        mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings);
 
         mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
         verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
@@ -105,7 +110,7 @@
         int imeInsetAmount = 100;
         int systemBarInsetAmount = 10;
 
-        mKeyguardSecurityContainer.setOneHandedMode(/* oneHandedMode= */false);
+        mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings);
 
         Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
         Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
@@ -129,7 +134,7 @@
         int imeInsetAmount = 0;
         int systemBarInsetAmount = 10;
 
-        mKeyguardSecurityContainer.setOneHandedMode(/* oneHandedMode= */false);
+        mKeyguardSecurityContainer.initMode(MODE_DEFAULT, mGlobalSettings);
 
         Insets imeInset = Insets.of(0, 0, 0, imeInsetAmount);
         Insets systemBarInset = Insets.of(0, 0, 0, systemBarInsetAmount);
@@ -148,8 +153,8 @@
     }
 
     private void setupForUpdateKeyguardPosition(boolean oneHandedMode) {
-        mKeyguardSecurityContainer.setOneHandedMode(oneHandedMode);
-        mKeyguardSecurityContainer.setOneHandedModeLeftAligned(true, false);
+        int mode = oneHandedMode ? MODE_ONE_HANDED : MODE_DEFAULT;
+        mKeyguardSecurityContainer.initMode(mode, mGlobalSettings);
 
         mKeyguardSecurityContainer.measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
         mKeyguardSecurityContainer.layout(0, 0, SCREEN_WIDTH, SCREEN_WIDTH);
@@ -160,29 +165,28 @@
     }
 
     @Test
-    public void setIsLeftAligned_movesKeyguard() {
+    public void updatePosition_movesKeyguard() {
         setupForUpdateKeyguardPosition(/* oneHandedMode= */ true);
+        mKeyguardSecurityContainer.updatePositionByTouchX(
+                mKeyguardSecurityContainer.getWidth() - 1f);
 
-        mKeyguardSecurityContainer.setOneHandedModeLeftAligned(
-                /* leftAligned= */false, /* animate= */false);
         verify(mSecurityViewFlipper).setTranslationX(
                 mKeyguardSecurityContainer.getWidth() - mSecurityViewFlipper.getWidth());
 
-        mKeyguardSecurityContainer.setOneHandedModeLeftAligned(
-                /* leftAligned= */true, /* animate= */false);
+        mKeyguardSecurityContainer.updatePositionByTouchX(1f);
+
         verify(mSecurityViewFlipper).setTranslationX(0.0f);
     }
 
     @Test
-    public void setIsLeftAligned_doesntMoveTwoHandedKeyguard() {
+    public void updatePosition_doesntMoveTwoHandedKeyguard() {
         setupForUpdateKeyguardPosition(/* oneHandedMode= */ false);
 
-        mKeyguardSecurityContainer.setOneHandedModeLeftAligned(
-                /* leftAligned= */false, /* animate= */false);
+        mKeyguardSecurityContainer.updatePositionByTouchX(
+                mKeyguardSecurityContainer.getWidth() - 1f);
         verify(mSecurityViewFlipper, never()).setTranslationX(anyInt());
 
-        mKeyguardSecurityContainer.setOneHandedModeLeftAligned(
-                /* leftAligned= */true, /* animate= */false);
+        mKeyguardSecurityContainer.updatePositionByTouchX(1f);
         verify(mSecurityViewFlipper, never()).setTranslationX(anyInt());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index ff5960b..de8cc89 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -19,6 +19,7 @@
 import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
 import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
 
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -961,6 +962,19 @@
     }
 
     @Test
+    public void testStartUdfpsServiceStrongAuthRequiredAfterTimeout() {
+        // GIVEN status bar state is on the keyguard
+        mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
+
+        // WHEN user loses smart unlock trust
+        when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
+                .thenReturn(SOME_AUTH_REQUIRED_AFTER_USER_REQUEST);
+
+        // THEN we should still listen for udfps
+        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(true);
+    }
+
+    @Test
     public void testShouldNotListenForUdfps_whenTrustEnabled() {
         // GIVEN a "we should listen for udfps" state
         mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
index 77286b1..796af11 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/IWindowMagnificationConnectionTest.java
@@ -64,7 +64,7 @@
     @Mock
     private IWindowMagnificationConnectionCallback mConnectionCallback;
     @Mock
-    private WindowMagnificationAnimationController mWindowMagnificationAnimationController;
+    private WindowMagnificationController mWindowMagnificationController;
     @Mock
     private ModeSwitchesController mModeSwitchesController;
     @Mock
@@ -89,7 +89,7 @@
         mWindowMagnification = new WindowMagnification(getContext(),
                 getContext().getMainThreadHandler(), mCommandQueue,
                 mModeSwitchesController, mSysUiState, mOverviewProxyService);
-        mWindowMagnification.mAnimationControllerSupplier = new FakeAnimationControllerSupplier(
+        mWindowMagnification.mMagnificationControllerSupplier = new FakeControllerSupplier(
                 mContext.getSystemService(DisplayManager.class));
 
         mWindowMagnification.requestWindowMagnificationConnection(true);
@@ -100,11 +100,11 @@
     @Test
     public void enableWindowMagnification_passThrough() throws RemoteException {
         mIWindowMagnificationConnection.enableWindowMagnification(TEST_DISPLAY, 3.0f, Float.NaN,
-                Float.NaN, mAnimationCallback);
+                Float.NaN, 0f, 0f, mAnimationCallback);
         waitForIdleSync();
 
-        verify(mWindowMagnificationAnimationController).enableWindowMagnification(eq(3.0f),
-                eq(Float.NaN), eq(Float.NaN), eq(mAnimationCallback));
+        verify(mWindowMagnificationController).enableWindowMagnification(eq(3.0f),
+                eq(Float.NaN), eq(Float.NaN), eq(0f), eq(0f), eq(mAnimationCallback));
     }
 
     @Test
@@ -113,7 +113,7 @@
                 mAnimationCallback);
         waitForIdleSync();
 
-        verify(mWindowMagnificationAnimationController).deleteWindowMagnification(
+        verify(mWindowMagnificationController).deleteWindowMagnification(
                 mAnimationCallback);
     }
 
@@ -122,7 +122,7 @@
         mIWindowMagnificationConnection.setScale(TEST_DISPLAY, 3.0f);
         waitForIdleSync();
 
-        verify(mWindowMagnificationAnimationController).setScale(3.0f);
+        verify(mWindowMagnificationController).setScale(3.0f);
     }
 
     @Test
@@ -130,7 +130,7 @@
         mIWindowMagnificationConnection.moveWindowMagnifier(TEST_DISPLAY, 100f, 200f);
         waitForIdleSync();
 
-        verify(mWindowMagnificationAnimationController).moveWindowMagnifier(100f, 200f);
+        verify(mWindowMagnificationController).moveWindowMagnifier(100f, 200f);
     }
 
     @Test
@@ -151,16 +151,16 @@
         verify(mModeSwitchesController).removeButton(TEST_DISPLAY);
     }
 
-    private class FakeAnimationControllerSupplier extends
-            DisplayIdIndexSupplier<WindowMagnificationAnimationController> {
+    private class FakeControllerSupplier extends
+            DisplayIdIndexSupplier<WindowMagnificationController> {
 
-        FakeAnimationControllerSupplier(DisplayManager displayManager) {
+        FakeControllerSupplier(DisplayManager displayManager) {
             super(displayManager);
         }
 
         @Override
-        protected WindowMagnificationAnimationController createInstance(Display display) {
-            return mWindowMagnificationAnimationController;
+        protected WindowMagnificationController createInstance(Display display) {
+            return mWindowMagnificationController;
         }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/TestableWindowManager.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/TestableWindowManager.java
index 8bb9d42..44770fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/TestableWindowManager.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/TestableWindowManager.java
@@ -110,7 +110,7 @@
     }
 
     /**
-     * Sets the given window insets to the current window metics.
+     * Sets the given window insets to the current window metrics.
      *
      * @param insets the window insets.
      */
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 148c6ef..3cc177d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationAnimationControllerTest.java
@@ -17,22 +17,27 @@
 package com.android.systemui.accessibility;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 import android.animation.ValueAnimator;
 import android.annotation.Nullable;
 import android.app.Instrumentation;
 import android.content.Context;
+import android.graphics.Rect;
 import android.os.Handler;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.testing.AndroidTestingRunner;
 import android.view.SurfaceControl;
+import android.view.View;
+import android.view.WindowManager;
 import android.view.accessibility.IRemoteMagnificationAnimationCallback;
 import android.view.animation.AccelerateInterpolator;
 
@@ -40,6 +45,7 @@
 import androidx.test.filters.LargeTest;
 
 import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
+import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.model.SysUiState;
 
@@ -56,7 +62,6 @@
 
 import java.util.concurrent.atomic.AtomicReference;
 
-
 @Ignore
 @LargeTest
 @RunWith(AndroidTestingRunner.class)
@@ -74,6 +79,8 @@
     private ArgumentCaptor<Float> mScaleCaptor = ArgumentCaptor.forClass(Float.class);
     private ArgumentCaptor<Float> mCenterXCaptor = ArgumentCaptor.forClass(Float.class);
     private ArgumentCaptor<Float> mCenterYCaptor = ArgumentCaptor.forClass(Float.class);
+    private final ArgumentCaptor<Float> mOffsetXCaptor = ArgumentCaptor.forClass(Float.class);
+    private final ArgumentCaptor<Float> mOffsetYCaptor = ArgumentCaptor.forClass(Float.class);
 
     @Mock
     Handler mHandler;
@@ -94,18 +101,25 @@
     private long mWaitingAnimationPeriod;
     private long mWaitIntermediateAnimationPeriod;
 
+    private TestableWindowManager mWindowManager;
+
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
+        final WindowManager wm = mContext.getSystemService(WindowManager.class);
+        mWindowManager = spy(new TestableWindowManager(wm));
+        mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
+
         mWaitingAnimationPeriod = 2 * ANIMATION_DURATION_MS;
         mWaitIntermediateAnimationPeriod = ANIMATION_DURATION_MS / 2;
+        mWindowMagnificationAnimationController = new WindowMagnificationAnimationController(
+                mContext, newValueAnimator());
         mController = new SpyWindowMagnificationController(mContext, mHandler,
+                mWindowMagnificationAnimationController,
                 mSfVsyncFrameProvider, null, new SurfaceControl.Transaction(),
                 mWindowMagnifierCallback, mSysUiState);
         mSpyController = mController.getSpyController();
-        mWindowMagnificationAnimationController = new WindowMagnificationAnimationController(
-                mContext, mController, newValueAnimator());
     }
 
     @After
@@ -118,12 +132,15 @@
             throws RemoteException {
         enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback);
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnification(
+        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
                 mScaleCaptor.capture(),
-                mCenterXCaptor.capture(), mCenterYCaptor.capture());
+                mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+                mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
         verifyStartValue(mScaleCaptor, 1.0f);
         verifyStartValue(mCenterXCaptor, DEFAULT_CENTER_X);
         verifyStartValue(mCenterYCaptor, DEFAULT_CENTER_Y);
+        verifyStartValue(mOffsetXCaptor, 0f);
+        verifyStartValue(mOffsetYCaptor, 0f);
         verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X, DEFAULT_CENTER_Y);
         verify(mAnimationCallback).onResult(true);
     }
@@ -161,8 +178,8 @@
                 });
         SystemClock.sleep(mWaitingAnimationPeriod);
 
-        verify(mSpyController).enableWindowMagnification(1, DEFAULT_CENTER_X,
-                DEFAULT_CENTER_Y);
+        verify(mSpyController).enableWindowMagnificationInternal(1, DEFAULT_CENTER_X,
+                DEFAULT_CENTER_Y, 0f, 0f);
         verify(mAnimationCallback).onResult(true);
     }
 
@@ -186,11 +203,15 @@
 
         SystemClock.sleep(mWaitingAnimationPeriod);
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
-                mCenterXCaptor.capture(), mCenterYCaptor.capture());
+        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+                mScaleCaptor.capture(),
+                mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+                mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
         verifyStartValue(mScaleCaptor, mCurrentScale.get());
         verifyStartValue(mCenterXCaptor, mCurrentCenterX.get());
         verifyStartValue(mCenterYCaptor, mCurrentCenterY.get());
+        verifyStartValue(mOffsetXCaptor, 0f);
+        verifyStartValue(mOffsetYCaptor, 0f);
         verifyFinalSpec(targetScale, targetCenterX, targetCenterY);
         verify(mAnimationCallback).onResult(false);
         verify(mAnimationCallback2).onResult(true);
@@ -212,11 +233,15 @@
 
         SystemClock.sleep(mWaitingAnimationPeriod);
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
-                mCenterXCaptor.capture(), mCenterYCaptor.capture());
+        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+                mScaleCaptor.capture(),
+                mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+                mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
         verifyStartValue(mScaleCaptor, mCurrentScale.get());
         verifyStartValue(mCenterXCaptor, mCurrentCenterX.get());
         verifyStartValue(mCenterYCaptor, mCurrentCenterY.get());
+        verifyStartValue(mOffsetXCaptor, 0f);
+        verifyStartValue(mOffsetYCaptor, 0f);
         // It presents the window magnification is disabled.
         verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
 
@@ -255,7 +280,7 @@
         });
         SystemClock.sleep(mWaitingAnimationPeriod);
 
-        verify(mSpyController, never()).enableWindowMagnification(anyFloat(), anyFloat(),
+        verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
                 anyFloat());
         verify(mAnimationCallback).onResult(false);
         verify(mAnimationCallback2).onResult(true);
@@ -285,9 +310,10 @@
         verify(mAnimationCallback).onResult(false);
         SystemClock.sleep(mWaitingAnimationPeriod);
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnification(
+        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
                 mScaleCaptor.capture(),
-                mCenterXCaptor.capture(), mCenterYCaptor.capture());
+                mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+                mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
         //Animating in reverse, so we only check if the start values are greater than current.
         assertTrue(mScaleCaptor.getAllValues().get(0) > mCurrentScale.get());
         assertEquals(targetScale, mScaleCaptor.getValue(), 0f);
@@ -335,7 +361,7 @@
         });
         SystemClock.sleep(mWaitingAnimationPeriod);
 
-        verify(mSpyController, never()).enableWindowMagnification(anyFloat(), anyFloat(),
+        verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
                 anyFloat());
         verify(mSpyController, never()).deleteWindowMagnification();
         verify(mAnimationCallback).onResult(false);
@@ -361,50 +387,71 @@
 
         SystemClock.sleep(mWaitingAnimationPeriod);
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
-                mCenterXCaptor.capture(), mCenterYCaptor.capture());
+        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+                mScaleCaptor.capture(),
+                mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+                mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
         verifyStartValue(mScaleCaptor, mCurrentScale.get());
         verifyStartValue(mCenterXCaptor, mCurrentCenterX.get());
         verifyStartValue(mCenterYCaptor, mCurrentCenterY.get());
+        verifyStartValue(mOffsetXCaptor, 0f);
+        verifyStartValue(mOffsetYCaptor, 0f);
         verifyFinalSpec(targetScale, targetCenterX, targetCenterY);
         verify(mAnimationCallback2).onResult(true);
     }
 
     @Test
+    public void enableWindowMagnificationWithOffset_expectedValues() {
+        final float offsetRatio = -0.1f;
+        final Rect windowBounds = new Rect(mWindowManager.getCurrentWindowMetrics().getBounds());
+        mInstrumentation.runOnMainSync(() -> {
+            Mockito.reset(mSpyController);
+            mWindowMagnificationAnimationController.enableWindowMagnification(DEFAULT_SCALE,
+                    windowBounds.exactCenterX(), windowBounds.exactCenterY(),
+                    offsetRatio, offsetRatio, mAnimationCallback);
+        });
+        SystemClock.sleep(mWaitingAnimationPeriod);
+        final View attachedView = mWindowManager.getAttachedView();
+        assertNotNull(attachedView);
+        final Rect mirrorViewBound = new Rect();
+        final View mirrorView = attachedView.findViewById(R.id.surface_view);
+        assertNotNull(mirrorView);
+        mirrorView.getBoundsOnScreen(mirrorViewBound);
+
+        assertEquals(mirrorViewBound.exactCenterX() - windowBounds.exactCenterX(),
+                Math.round(offsetRatio * mirrorViewBound.width() / 2), 0.1f);
+        assertEquals(mirrorViewBound.exactCenterY() - windowBounds.exactCenterY(),
+                Math.round(offsetRatio * mirrorViewBound.height() / 2), 0.1f);
+    }
+
+    @Test
     public void enableWindowMagnificationWithSameScale_enabled_doNothingButInvokeCallback()
             throws RemoteException {
         enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, null);
 
         enableWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback);
 
-        verify(mSpyController, never()).enableWindowMagnification(anyFloat(), anyFloat(),
+        verify(mSpyController, never()).enableWindowMagnificationInternal(anyFloat(), anyFloat(),
                 anyFloat());
         verify(mAnimationCallback).onResult(true);
     }
 
     @Test
-    public void setScale_enabled_expectedScale() {
-        enableWindowMagnificationWithoutAnimation();
-
-        mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationAnimationController.setScale(DEFAULT_SCALE + 1));
-
-        verify(mSpyController).setScale(DEFAULT_SCALE + 1);
-        verifyFinalSpec(DEFAULT_SCALE + 1, DEFAULT_CENTER_X, DEFAULT_CENTER_Y);
-    }
-
-    @Test
     public void deleteWindowMagnification_enabled_expectedValuesAndInvokeCallback()
             throws RemoteException {
         enableWindowMagnificationWithoutAnimation();
 
         deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback);
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
-                mCenterXCaptor.capture(), mCenterYCaptor.capture());
+        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+                mScaleCaptor.capture(),
+                mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+                mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
         verifyStartValue(mScaleCaptor, DEFAULT_SCALE);
         verifyStartValue(mCenterXCaptor, Float.NaN);
         verifyStartValue(mCenterYCaptor, Float.NaN);
+        verifyStartValue(mOffsetXCaptor, 0f);
+        verifyStartValue(mOffsetYCaptor, 0f);
         verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
         verify(mAnimationCallback).onResult(true);
     }
@@ -443,8 +490,10 @@
                     mCurrentCenterY.set(mController.getCenterY());
                 });
         SystemClock.sleep(mWaitingAnimationPeriod);
-        verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
-                mCenterXCaptor.capture(), mCenterYCaptor.capture());
+        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+                mScaleCaptor.capture(),
+                mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+                mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
 
         //The animation is in verse, so we only check the start values should no be greater than
         // the current one.
@@ -452,6 +501,8 @@
         assertEquals(1.0f, mScaleCaptor.getValue(), 0f);
         verifyStartValue(mCenterXCaptor, Float.NaN);
         verifyStartValue(mCenterYCaptor, Float.NaN);
+        verifyStartValue(mOffsetXCaptor, 0f);
+        verifyStartValue(mOffsetYCaptor, 0f);
         verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
         verify(mAnimationCallback).onResult(false);
         verify(mAnimationCallback2).onResult(true);
@@ -481,9 +532,13 @@
 
         deleteWindowMagnificationAndWaitAnimating(mWaitingAnimationPeriod, mAnimationCallback2);
 
-        verify(mSpyController, atLeast(2)).enableWindowMagnification(mScaleCaptor.capture(),
-                mCenterXCaptor.capture(), mCenterYCaptor.capture());
+        verify(mSpyController, atLeast(2)).enableWindowMagnificationInternal(
+                mScaleCaptor.capture(),
+                mCenterXCaptor.capture(), mCenterYCaptor.capture(),
+                mOffsetXCaptor.capture(), mOffsetYCaptor.capture());
         assertEquals(1.0f, mScaleCaptor.getValue(), 0f);
+        verifyStartValue(mOffsetXCaptor, 0f);
+        verifyStartValue(mOffsetYCaptor, 0f);
         verifyFinalSpec(Float.NaN, Float.NaN, Float.NaN);
         verify(mAnimationCallback).onResult(false);
         verify(mAnimationCallback2).onResult(true);
@@ -508,26 +563,12 @@
         enableWindowMagnificationWithoutAnimation();
 
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationAnimationController.moveWindowMagnifier(100f, 200f));
+                () -> mController.moveWindowMagnifier(100f, 200f));
 
         verify(mSpyController).moveWindowMagnifier(100f, 200f);
         verifyFinalSpec(DEFAULT_SCALE, DEFAULT_CENTER_X + 100f, DEFAULT_CENTER_Y + 100f);
     }
 
-    @Test
-    public void onConfigurationChanged_passThrough() {
-        mWindowMagnificationAnimationController.onConfigurationChanged(100);
-
-        verify(mSpyController).onConfigurationChanged(100);
-    }
-
-    @Test
-    public void updateSysUiStateFlag_passThrough() {
-        mWindowMagnificationAnimationController.updateSysUiStateFlag();
-
-        verify(mSpyController).updateSysUIStateFlag();
-    }
-
     private void verifyFinalSpec(float expectedScale, float expectedCenterX,
             float expectedCenterY) {
         assertEquals(expectedScale, mController.getScale(), 0f);
@@ -581,11 +622,12 @@
         private WindowMagnificationController mSpyController;
 
         SpyWindowMagnificationController(Context context, Handler handler,
+                WindowMagnificationAnimationController animationController,
                 SfVsyncFrameCallbackProvider sfVsyncFrameProvider,
                 MirrorWindowControl mirrorWindowControl, SurfaceControl.Transaction transaction,
                 WindowMagnifierCallback callback, SysUiState sysUiState) {
-            super(context, handler, sfVsyncFrameProvider, mirrorWindowControl, transaction,
-                    callback, sysUiState);
+            super(context, handler, animationController, sfVsyncFrameProvider, mirrorWindowControl,
+                    transaction, callback, sysUiState);
             mSpyController = Mockito.mock(WindowMagnificationController.class);
         }
 
@@ -594,9 +636,18 @@
         }
 
         @Override
-        void enableWindowMagnification(float scale, float centerX, float centerY) {
-            super.enableWindowMagnification(scale, centerX, centerY);
-            mSpyController.enableWindowMagnification(scale, centerX, centerY);
+        void enableWindowMagnificationInternal(float scale, float centerX, float centerY) {
+            super.enableWindowMagnificationInternal(scale, centerX, centerY);
+            mSpyController.enableWindowMagnificationInternal(scale, centerX, centerY);
+        }
+
+        @Override
+        void enableWindowMagnificationInternal(float scale, float centerX, float centerY,
+                float magnificationOffsetFrameRatioX, float magnificationOffsetFrameRatioY) {
+            super.enableWindowMagnificationInternal(scale, centerX, centerY,
+                    magnificationOffsetFrameRatioX, magnificationOffsetFrameRatioY);
+            mSpyController.enableWindowMagnificationInternal(scale, centerX, centerY,
+                    magnificationOffsetFrameRatioX, magnificationOffsetFrameRatioY);
         }
 
         @Override
@@ -622,12 +673,6 @@
             super.updateSysUIStateFlag();
             mSpyController.updateSysUIStateFlag();
         }
-
-        @Override
-        void onConfigurationChanged(int configDiff) {
-            super.onConfigurationChanged(configDiff);
-            mSpyController.onConfigurationChanged(configDiff);
-        }
     }
 
     private static ValueAnimator newValueAnimator() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
index 70457cf..8fdcadd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationControllerTest.java
@@ -89,6 +89,8 @@
     @Mock
     private Handler mHandler;
     @Mock
+    private WindowMagnificationAnimationController mWindowMagnificationAnimationController;
+    @Mock
     private SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
     @Mock
     private MirrorWindowControl mMirrorWindowControl;
@@ -128,7 +130,7 @@
 
         mResources = getContext().getOrCreateTestableResources().getResources();
         mWindowMagnificationController = new WindowMagnificationController(mContext,
-                mHandler, mSfVsyncFrameProvider,
+                mHandler, mWindowMagnificationAnimationController, mSfVsyncFrameProvider,
                 mMirrorWindowControl, mTransaction, mWindowMagnifierCallback, mSysUiState);
 
         verify(mMirrorWindowControl).setWindowDelegate(
@@ -144,7 +146,7 @@
     @Test
     public void enableWindowMagnification_showControlAndNotifyBoundsChanged() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -157,7 +159,7 @@
     @Test
     public void enableWindowMagnification_systemGestureExclusionRectsIsSet() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
         // Wait for Rects updated.
@@ -174,11 +176,11 @@
         mWindowManager.setWindowBounds(new Rect(0, 0, screenSize, screenSize));
         //We need to initialize new one because the window size is determined when initialization.
         final WindowMagnificationController controller = new WindowMagnificationController(mContext,
-                mHandler, mSfVsyncFrameProvider,
+                mHandler, mWindowMagnificationAnimationController, mSfVsyncFrameProvider,
                 mMirrorWindowControl, mTransaction, mWindowMagnifierCallback, mSysUiState);
 
         mInstrumentation.runOnMainSync(() -> {
-            controller.enableWindowMagnification(Float.NaN, Float.NaN,
+            controller.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -193,7 +195,7 @@
     @Test
     public void deleteWindowMagnification_destroyControl() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -211,7 +213,7 @@
         setSystemGestureInsets();
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     bounds.bottom);
         });
         ReferenceTestUtils.waitForCondition(this::hasMagnificationOverlapFlag);
@@ -227,7 +229,7 @@
     @Test
     public void moveMagnifier_schedulesFrame() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             mWindowMagnificationController.moveWindowMagnifier(100f, 100f);
         });
@@ -244,8 +246,8 @@
         }).when(mHandler).postDelayed(any(Runnable.class), anyLong());
 
         mInstrumentation.runOnMainSync(
-                () -> mWindowMagnificationController.enableWindowMagnification(2.0f, Float.NaN,
-                        Float.NaN));
+                () -> mWindowMagnificationController.enableWindowMagnificationInternal(2.0f,
+                        Float.NaN, Float.NaN));
 
         mInstrumentation.runOnMainSync(() -> mWindowMagnificationController.setScale(3.0f));
 
@@ -281,8 +283,8 @@
         final float displayWidth = windowBounds.width();
         final PointF magnifiedCenter = new PointF(center, center + 5f);
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, magnifiedCenter.x,
-                    magnifiedCenter.y);
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN,
+                    magnifiedCenter.x, magnifiedCenter.y);
             // Get the center again in case the center we set is out of screen.
             magnifiedCenter.set(mWindowMagnificationController.getCenterX(),
                     mWindowMagnificationController.getCenterY());
@@ -325,7 +327,7 @@
         testWindowBounds.set(testWindowBounds.left, testWindowBounds.top,
                 testWindowBounds.right + 100, testWindowBounds.bottom + 100);
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
         mWindowManager.setWindowBounds(testWindowBounds);
@@ -345,7 +347,7 @@
     @Test
     public void screenSizeIsChangedToLarge_enabled_windowSizeIsConstrained() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
         final int screenSize = mContext.getResources().getDimensionPixelSize(
@@ -367,7 +369,7 @@
     @Test
     public void onDensityChanged_enabled_updateDimensionsAndResetWindowMagnification() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
             Mockito.reset(mWindowManager);
             Mockito.reset(mMirrorWindowControl);
@@ -396,7 +398,7 @@
     @Test
     public void initializeA11yNode_enabled_expectedValues() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(2.5f, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
                     Float.NaN);
         });
         final View mirrorView = mWindowManager.getAttachedView();
@@ -420,7 +422,7 @@
     public void performA11yActions_visible_expectedResults() {
         final int displayId = mContext.getDisplayId();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(2.5f, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
                     Float.NaN);
         });
 
@@ -447,7 +449,7 @@
     public void performA11yActions_visible_notifyAccessibilityActionPerformed() {
         final int displayId = mContext.getDisplayId();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(2.5f, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(2.5f, Float.NaN,
                     Float.NaN);
         });
 
@@ -460,7 +462,7 @@
     @Test
     public void enableWindowMagnification_hasA11yWindowTitle() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -471,12 +473,12 @@
     @Test
     public void enableWindowMagnificationWithScaleLessThanOne_enabled_disabled() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(0.9f, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(0.9f, Float.NaN,
                     Float.NaN);
         });
 
@@ -487,7 +489,7 @@
     public void onLocaleChanged_enabled_updateA11yWindowTitle() {
         final String newA11yWindowTitle = "new a11y window title";
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
         final TestableResources testableResources = getContext().getOrCreateTestableResources();
@@ -504,7 +506,7 @@
     @Test
     public void onSingleTap_enabled_scaleIsChanged() {
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
@@ -528,7 +530,7 @@
         final Rect bounds = mWindowManager.getCurrentWindowMetrics().getBounds();
         setSystemGestureInsets();
         mInstrumentation.runOnMainSync(() -> {
-            mWindowMagnificationController.enableWindowMagnification(Float.NaN, Float.NaN,
+            mWindowMagnificationController.enableWindowMagnificationInternal(Float.NaN, Float.NaN,
                     Float.NaN);
         });
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
index fb1716a..c898150 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/WindowMagnificationTest.java
@@ -167,30 +167,29 @@
 
     @Test
     public void overviewProxyIsConnected_controllerIsAvailable_updateSysUiStateFlag() {
-        final WindowMagnificationAnimationController mController = mock(
-                WindowMagnificationAnimationController.class);
-        mWindowMagnification.mAnimationControllerSupplier = new FakeAnimationControllerSupplier(
+        final WindowMagnificationController mController = mock(WindowMagnificationController.class);
+        mWindowMagnification.mMagnificationControllerSupplier = new FakeControllerSupplier(
                 mContext.getSystemService(DisplayManager.class), mController);
-        mWindowMagnification.mAnimationControllerSupplier.get(TEST_DISPLAY);
+        mWindowMagnification.mMagnificationControllerSupplier.get(TEST_DISPLAY);
 
         mOverviewProxyListener.onConnectionChanged(true);
 
-        verify(mController).updateSysUiStateFlag();
+        verify(mController).updateSysUIStateFlag();
     }
 
-    private static class FakeAnimationControllerSupplier extends
-            DisplayIdIndexSupplier<WindowMagnificationAnimationController> {
+    private static class FakeControllerSupplier extends
+            DisplayIdIndexSupplier<WindowMagnificationController> {
 
-        private final WindowMagnificationAnimationController mController;
+        private final WindowMagnificationController mController;
 
-        FakeAnimationControllerSupplier(DisplayManager displayManager,
-                WindowMagnificationAnimationController controller) {
+        FakeControllerSupplier(DisplayManager displayManager,
+                WindowMagnificationController controller) {
             super(displayManager);
             mController = controller;
         }
 
         @Override
-        protected WindowMagnificationAnimationController createInstance(Display display) {
+        protected WindowMagnificationController createInstance(Display display) {
             return mController;
         }
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
index cdf40a1..8ca17b9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/floatingmenu/AccessibilityFloatingMenuControllerTest.java
@@ -291,9 +291,12 @@
         mTargetsObserver = spy(Dependency.get(AccessibilityButtonTargetsObserver.class));
         mModeObserver = spy(Dependency.get(AccessibilityButtonModeObserver.class));
         mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
+        final AccessibilityFloatingMenuController controller =
+                new AccessibilityFloatingMenuController(mContextWrapper, mTargetsObserver,
+                        mModeObserver, mKeyguardUpdateMonitor);
+        controller.init();
 
-        return new AccessibilityFloatingMenuController(mContextWrapper, mTargetsObserver,
-                mModeObserver, mKeyguardUpdateMonitor);
+        return controller;
     }
 
     private void enableAccessibilityFloatingMenuConfig() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
index d4c3840..9bd33eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/DialogLaunchAnimatorTest.kt
@@ -16,6 +16,7 @@
 import junit.framework.Assert.assertEquals
 import junit.framework.Assert.assertFalse
 import junit.framework.Assert.assertTrue
+import org.junit.After
 import org.junit.Test
 import org.junit.runner.RunWith
 
@@ -28,24 +29,22 @@
     private val dialogLaunchAnimator =
         DialogLaunchAnimator(context, launchAnimator, hostDialogprovider)
 
+    private val attachedViews = mutableSetOf<View>()
+
+    @After
+    fun tearDown() {
+        runOnMainThreadAndWaitForIdleSync {
+            attachedViews.forEach {
+                ViewUtils.detachView(it)
+            }
+        }
+    }
+
     @Test
     fun testShowDialogFromView() {
         // Show the dialog. showFromView() must be called on the main thread with a dialog created
         // on the main thread too.
-        val (dialog, hostDialog) = runOnMainThreadAndWaitForIdleSync {
-            val touchSurfaceRoot = LinearLayout(context)
-            val touchSurface = View(context)
-            touchSurfaceRoot.addView(touchSurface)
-
-            // We need to attach the root to the window manager otherwise the exit animation will
-            // be skipped
-            ViewUtils.attachView(touchSurfaceRoot)
-
-            val dialog = TestDialog(context)
-            val hostDialog =
-                dialogLaunchAnimator.showFromView(dialog, touchSurface) as TestHostDialog
-            dialog to hostDialog
-        }
+        val (dialog, hostDialog) = createDialogAndHostDialog()
 
         // Only the host dialog is actually showing.
         assertTrue(hostDialog.isShowing)
@@ -100,6 +99,51 @@
         assertTrue(dialog.onStopCalled)
     }
 
+    @Test
+    fun testStackedDialogsDismissesAll() {
+        val (_, hostDialogFirst) = createDialogAndHostDialog()
+        val (dialogSecond, hostDialogSecond) = createDialogAndHostDialogFromDialog(hostDialogFirst)
+
+        runOnMainThreadAndWaitForIdleSync {
+            dialogLaunchAnimator.disableAllCurrentDialogsExitAnimations()
+            dialogSecond.dismissStack()
+        }
+
+        assertTrue(hostDialogSecond.wasDismissed)
+        assertTrue(hostDialogFirst.wasDismissed)
+    }
+
+    private fun createDialogAndHostDialog(): Pair<TestDialog, TestHostDialog> {
+        return runOnMainThreadAndWaitForIdleSync {
+            val touchSurfaceRoot = LinearLayout(context)
+            val touchSurface = View(context)
+            touchSurfaceRoot.addView(touchSurface)
+
+            // We need to attach the root to the window manager otherwise the exit animation will
+            // be skipped
+            ViewUtils.attachView(touchSurfaceRoot)
+            attachedViews.add(touchSurfaceRoot)
+
+            val dialog = TestDialog(context)
+            val hostDialog =
+                    dialogLaunchAnimator.showFromView(dialog, touchSurface) as TestHostDialog
+            dialog to hostDialog
+        }
+    }
+
+    private fun createDialogAndHostDialogFromDialog(
+        hostParent: Dialog
+    ): Pair<TestDialog, TestHostDialog> {
+        return runOnMainThreadAndWaitForIdleSync {
+            val dialog = TestDialog(context)
+            val hostDialog = dialogLaunchAnimator.showFromDialog(
+                    dialog,
+                    hostParent
+            ) as TestHostDialog
+            dialog to hostDialog
+        }
+    }
+
     private fun <T : Any> runOnMainThreadAndWaitForIdleSync(f: () -> T): T {
         lateinit var result: T
         context.mainExecutor.execute {
@@ -198,6 +242,11 @@
             notifyListeners { onShow() }
         }
 
+        fun dismissStack() {
+            notifyListeners { prepareForStackDismiss() }
+            dismiss()
+        }
+
         private fun notifyListeners(notify: DialogListener.() -> Unit) {
             for (listener in HashSet(listeners)) {
                 listener.notify()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt
index 58e0cb2..3696ec5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/GhostedViewLaunchAnimatorControllerTest.kt
@@ -16,22 +16,53 @@
 
 package com.android.systemui.animation
 
+import android.graphics.drawable.Drawable
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
-import android.widget.LinearLayout
+import android.view.View
+import android.view.ViewGroup
+import android.view.ViewParent
 import androidx.test.filters.SmallTest
+import com.android.internal.jank.InteractionJankMonitor
 import com.android.systemui.SysuiTestCase
+import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.MockitoAnnotations
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
 @TestableLooper.RunWithLooper
 class GhostedViewLaunchAnimatorControllerTest : SysuiTestCase() {
+    @Mock lateinit var interactionJankMonitor: InteractionJankMonitor
+    @Mock lateinit var view: View
+    @Mock lateinit var rootView: ViewGroup
+    @Mock lateinit var viewParent: ViewParent
+    @Mock lateinit var drawable: Drawable
+    lateinit var controller: GhostedViewLaunchAnimatorController
+
+    @Before
+    fun setup() {
+        MockitoAnnotations.initMocks(this)
+        whenever(view.rootView).thenReturn(rootView)
+        whenever(view.background).thenReturn(drawable)
+        whenever(view.height).thenReturn(0)
+        whenever(view.width).thenReturn(0)
+        whenever(view.parent).thenReturn(viewParent)
+        whenever(view.visibility).thenReturn(View.VISIBLE)
+        whenever(view.invalidate()).then { /* NO-OP */ }
+        whenever(view.getLocationOnScreen(any())).then { /* NO-OP */ }
+        whenever(interactionJankMonitor.begin(any(), anyInt())).thenReturn(true)
+        whenever(interactionJankMonitor.end(anyInt())).thenReturn(true)
+        controller = GhostedViewLaunchAnimatorController(view, 0, interactionJankMonitor)
+    }
+
     @Test
     fun animatingOrphanViewDoesNotCrash() {
-        val ghostedView = LinearLayout(mContext)
-        val controller = GhostedViewLaunchAnimatorController(ghostedView)
         val state = LaunchAnimator.State(top = 0, bottom = 0, left = 0, right = 0)
 
         controller.onIntentStarted(willAnimate = true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index d90eb73..241b02d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -16,8 +16,6 @@
 
 package com.android.systemui.biometrics;
 
-import static android.media.AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY;
-
 import static junit.framework.Assert.assertEquals;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -44,6 +42,7 @@
 import android.os.Handler;
 import android.os.PowerManager;
 import android.os.RemoteException;
+import android.os.VibrationAttributes;
 import android.os.Vibrator;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper.RunWithLooper;
@@ -642,17 +641,17 @@
         mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent);
         moveEvent.recycle();
 
-        // THEN click haptic is played
+        // THEN low-tick haptic is played
         verify(mVibrator).vibrate(
                 anyInt(),
                 anyString(),
-                eq(mUdfpsController.EFFECT_CLICK),
-                eq("udfps-onStart"),
-                eq(UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES));
+                any(),
+                eq("udfps-onStart-tick"),
+                eq(UdfpsController.VIBRATION_ATTRIBUTES));
 
         // THEN make sure vibration attributes has so that it always will play the haptic,
         // even in battery saver mode
-        assertEquals(USAGE_ASSISTANCE_ACCESSIBILITY,
-                UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES.getUsage());
+        assertEquals(VibrationAttributes.USAGE_COMMUNICATION_REQUEST,
+                UdfpsController.VIBRATION_ATTRIBUTES.getUsage());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index 0e86964..1cf21ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -351,9 +351,8 @@
         mSystemClock.advanceTime(205);
         mController.onTouchOutsideView();
 
-        // THEN show the bouncer and reset alt auth
+        // THEN show the bouncer
         verify(mStatusBarKeyguardViewManager).showBouncer(eq(true));
-        verify(mStatusBarKeyguardViewManager).resetAlternateAuth(anyBoolean());
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourcePrimerTest.java b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourcePrimerTest.java
new file mode 100644
index 0000000..659b1a3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/communal/CommunalSourcePrimerTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2021 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.communal;
+
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.testing.AndroidTestingRunner;
+
+import androidx.concurrent.futures.CallbackToFutureAdapter;
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+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.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Optional;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class CommunalSourcePrimerTest extends SysuiTestCase {
+    private static final String TEST_COMPONENT_NAME = "com.google.tests/.CommunalService";
+    private static final int MAX_RETRIES = 5;
+    private static final int RETRY_DELAY_MS = 1000;
+
+    @Mock
+    private Context mContext;
+
+    @Mock
+    private Resources mResources;
+
+    private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
+
+    @Mock
+    private CommunalSource mSource;
+
+    @Mock
+    private CommunalSourceMonitor mCommunalSourceMonitor;
+
+    @Mock
+    private CommunalSource.Connector mConnector;
+
+    @Mock
+    private CommunalSource.Observer mObserver;
+
+    private CommunalSourcePrimer mPrimer;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        when(mResources.getInteger(R.integer.config_communalSourceMaxReconnectAttempts))
+                .thenReturn(MAX_RETRIES);
+        when(mResources.getInteger(R.integer.config_communalSourceReconnectBaseDelay))
+                .thenReturn(RETRY_DELAY_MS);
+        when(mResources.getString(R.string.config_communalSourceComponent))
+                .thenReturn(TEST_COMPONENT_NAME);
+
+        mPrimer = new CommunalSourcePrimer(mContext, mResources, mFakeExecutor,
+                mCommunalSourceMonitor, Optional.of(mConnector), Optional.of(mObserver));
+    }
+
+    @Test
+    public void testConnect() {
+        when(mConnector.connect()).thenReturn(
+                CallbackToFutureAdapter.getFuture(completer -> {
+                    completer.set(Optional.of(mSource));
+                    return "test";
+                }));
+
+        mPrimer.onBootCompleted();
+        mFakeExecutor.runAllReady();
+        verify(mCommunalSourceMonitor).setSource(mSource);
+    }
+
+    @Test
+    public void testRetryOnBindFailure() throws Exception {
+        when(mConnector.connect()).thenReturn(
+                CallbackToFutureAdapter.getFuture(completer -> {
+                    completer.set(Optional.empty());
+                    return "test";
+                }));
+
+        mPrimer.onBootCompleted();
+        mFakeExecutor.runAllReady();
+
+        // Verify attempts happen. Note that we account for the retries plus initial attempt, which
+        // is not scheduled.
+        for (int attemptCount = 0; attemptCount < MAX_RETRIES + 1; attemptCount++) {
+            verify(mConnector, times(1)).connect();
+            clearInvocations(mConnector);
+            mFakeExecutor.advanceClockToNext();
+            mFakeExecutor.runAllReady();
+        }
+
+        verify(mCommunalSourceMonitor, never()).setSource(Mockito.notNull());
+    }
+
+    @Test
+    public void testAttemptOnPackageChange() {
+        when(mConnector.connect()).thenReturn(
+                CallbackToFutureAdapter.getFuture(completer -> {
+                    completer.set(Optional.empty());
+                    return "test";
+                }));
+
+        mPrimer.onBootCompleted();
+        mFakeExecutor.runAllReady();
+
+        final ArgumentCaptor<CommunalSource.Observer.Callback> callbackCaptor =
+                ArgumentCaptor.forClass(CommunalSource.Observer.Callback.class);
+        verify(mObserver).addCallback(callbackCaptor.capture());
+
+        clearInvocations(mConnector);
+        callbackCaptor.getValue().onSourceChanged();
+
+        verify(mConnector, times(1)).connect();
+    }
+
+    @Test
+    public void testDisconnect() {
+        final ArgumentCaptor<CommunalSource.Callback> callbackCaptor =
+                ArgumentCaptor.forClass(CommunalSource.Callback.class);
+
+        when(mConnector.connect()).thenReturn(
+                CallbackToFutureAdapter.getFuture(completer -> {
+                    completer.set(Optional.of(mSource));
+                    return "test";
+                }));
+
+        mPrimer.onBootCompleted();
+        mFakeExecutor.runAllReady();
+        verify(mCommunalSourceMonitor).setSource(mSource);
+        verify(mSource).addCallback(callbackCaptor.capture());
+
+        clearInvocations(mConnector);
+        callbackCaptor.getValue().onDisconnected();
+        mFakeExecutor.runAllReady();
+
+        verify(mConnector).connect();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index 886f84e..5b472ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -51,6 +51,7 @@
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.policy.DevicePostureController;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.concurrency.FakeThreadFactory;
@@ -93,6 +94,8 @@
     DevicePostureController mDevicePostureController;
     @Mock
     DozeLog mDozeLog;
+    @Mock
+    private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
     private FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
     private FakeThreadFactory mFakeThreadFactory = new FakeThreadFactory(mFakeExecutor);
 
@@ -130,7 +133,8 @@
                 mWakefulnessLifecycle,
                 mDozeParameters,
                 mDevicePostureController,
-                mDozeLog);
+                mDozeLog,
+                mUnlockedScreenOffAnimationController);
     }
 
     @Test
@@ -236,7 +240,8 @@
                 mWakefulnessLifecycle,
                 mDozeParameters,
                 mDevicePostureController,
-                mDozeLog);
+                mDozeLog,
+                mUnlockedScreenOffAnimationController);
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE);
         reset(mDozeHost);
@@ -273,7 +278,8 @@
                 mWakefulnessLifecycle,
                 mDozeParameters,
                 mDevicePostureController,
-                mDozeLog);
+                mDozeLog,
+                mUnlockedScreenOffAnimationController);
 
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE_AOD);
@@ -304,7 +310,8 @@
                 mWakefulnessLifecycle,
                 mDozeParameters,
                 mDevicePostureController,
-                mDozeLog);
+                mDozeLog,
+                mUnlockedScreenOffAnimationController);
 
         // GIVEN the device is in AOD
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -342,7 +349,8 @@
                 mWakefulnessLifecycle,
                 mDozeParameters,
                 mDevicePostureController,
-                mDozeLog);
+                mDozeLog,
+                mUnlockedScreenOffAnimationController);
 
         // GIVEN device is in AOD
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
@@ -384,7 +392,8 @@
                 mWakefulnessLifecycle,
                 mDozeParameters,
                 mDevicePostureController,
-                mDozeLog);
+                mDozeLog,
+                mUnlockedScreenOffAnimationController);
         verify(mDevicePostureController).addCallback(postureCallbackCaptor.capture());
 
         // GIVEN device is in AOD
@@ -466,24 +475,26 @@
     }
 
     @Test
-    public void transitionToDoze_duringScreenOff_afterTimeout_clampsToDim() {
+    public void transitionToDoze_duringUnlockedScreenOff_afterTimeout_clampsToDim() {
         when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
                 PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
         when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true);
+        when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true);
 
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE);
 
         // If we're dozing after a timeout, and playing the unlocked screen animation, we should
-        // stay at dim brightness, because the screen dims just before timeout.
-        assertEquals(mServiceFake.screenBrightness, DIM_BRIGHTNESS);
+        // stay at or below dim brightness, because the screen dims just before timeout.
+        assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS);
     }
 
     @Test
-    public void transitionToDoze_duringScreenOff_notAfterTimeout_doesNotClampToDim() {
+    public void transitionToDoze_duringUnlockedScreenOff_notAfterTimeout_doesNotClampToDim() {
         when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
                 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
         when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(true);
+        when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(true);
 
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE);
@@ -494,10 +505,11 @@
     }
 
     @Test
-    public void transitionToDoze_duringScreenOff_afterTimeout_noScreenOff_doesNotClampToDim() {
+    public void transitionToDoze_duringUnlockedScreenOff_afterTimeout_noScreenOff_doesNotClampToDim() {
         when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
                 PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
         when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
+        when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false);
 
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE);
@@ -506,6 +518,36 @@
         assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
     }
 
+    @Test
+    public void transitionToDoze_duringLockedScreenOff_afterTimeout_clampsToDim() {
+        when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
+                PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+        when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
+                WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
+        when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
+        when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false);
+
+        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+        mScreen.transitionTo(INITIALIZED, DOZE);
+
+        assertTrue(mServiceFake.screenBrightness <= DIM_BRIGHTNESS);
+    }
+
+    @Test
+    public void transitionToDoze_duringLockedScreenOff_notAfterTimeout_doesNotClampToDim() {
+        when(mWakefulnessLifecycle.getLastSleepReason()).thenReturn(
+                PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
+        when(mWakefulnessLifecycle.getWakefulness()).thenReturn(
+                WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP);
+        when(mDozeParameters.shouldControlUnlockedScreenOff()).thenReturn(false);
+        when(mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying()).thenReturn(false);
+
+        mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+        mScreen.transitionTo(INITIALIZED, DOZE);
+
+        assertEquals(mServiceFake.screenBrightness, DEFAULT_BRIGHTNESS);
+    }
+
     private void waitForSensorManager() {
         mFakeExecutor.runAllReady();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
index 150ab77..3e19cc4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -82,6 +82,8 @@
     private UdfpsController mUdfpsController;
     @Mock
     private DozeLog mDozeLog;
+    @Mock
+    private DozeScreenBrightness mDozeScreenBrightness;
 
     @Before
     public void setUp() throws Exception {
@@ -96,7 +98,8 @@
         mHandlerFake = new FakeHandler(Looper.getMainLooper());
         mWakeLock = new WakeLockFake();
         mScreen = new DozeScreenState(mServiceFake, mHandlerFake, mDozeHost, mDozeParameters,
-                mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog);
+                mWakeLock, mAuthController, mUdfpsControllerProvider, mDozeLog,
+                mDozeScreenBrightness);
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index f525fee..f207b9e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.doze;
 
 import static com.android.systemui.doze.DozeLog.REASON_SENSOR_TAP;
+import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS;
 import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN;
 
 import static org.junit.Assert.assertEquals;
@@ -37,6 +38,7 @@
 import android.database.ContentObserver;
 import android.hardware.Sensor;
 import android.hardware.display.AmbientDisplayConfiguration;
+import android.os.UserHandle;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
@@ -57,6 +59,8 @@
 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;
 
@@ -94,6 +98,13 @@
     private DevicePostureController mDevicePostureController;
     @Mock
     private ProximitySensor mProximitySensor;
+
+    // Capture listeners so that they can be used to send events
+    @Captor
+    private ArgumentCaptor<AuthController.Callback> mAuthControllerCallbackCaptor =
+            ArgumentCaptor.forClass(AuthController.Callback.class);
+    private AuthController.Callback mAuthControllerCallback;
+
     private FakeSettings mFakeSettings = new FakeSettings();
     private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener;
     private TestableLooper mTestableLooper;
@@ -105,14 +116,18 @@
         MockitoAnnotations.initMocks(this);
         mTestableLooper = TestableLooper.get(this);
         when(mAmbientDisplayConfiguration.tapSensorTypeMapping())
-                .thenReturn(new String[]{"tapSEnsor"});
+                .thenReturn(new String[]{"tapSensor"});
         when(mAmbientDisplayConfiguration.getWakeLockScreenDebounce()).thenReturn(5000L);
         when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
+        when(mAmbientDisplayConfiguration.enabled(UserHandle.USER_CURRENT)).thenReturn(true);
         doAnswer(invocation -> {
             ((Runnable) invocation.getArgument(0)).run();
             return null;
         }).when(mWakeLock).wrap(any(Runnable.class));
         mDozeSensors = new TestableDozeSensors();
+
+        verify(mAuthController).addCallback(mAuthControllerCallbackCaptor.capture());
+        mAuthControllerCallback = mAuthControllerCallbackCaptor.getValue();
     }
 
     @Test
@@ -375,6 +390,47 @@
                         "some other name"));
     }
 
+    @Test
+    public void testUdfpsEnrollmentChanged() throws Exception {
+        // GIVEN a UDFPS_LONG_PRESS trigger sensor that's not configured
+        Sensor mockSensor = mock(Sensor.class);
+        TriggerSensor triggerSensor = mDozeSensors.createDozeSensor(
+                mockSensor,
+                REASON_SENSOR_UDFPS_LONG_PRESS,
+                /* configured */ false);
+        mDozeSensors.addSensor(triggerSensor);
+        when(mSensorManager.requestTriggerSensor(eq(triggerSensor), eq(mockSensor)))
+                .thenReturn(true);
+
+        // WHEN listening state is set to TRUE
+        mDozeSensors.setListening(true, true);
+
+        // THEN mRegistered is still false b/c !mConfigured
+        assertFalse(triggerSensor.mConfigured);
+        assertFalse(triggerSensor.mRegistered);
+
+        // WHEN enrollment changes to TRUE
+        when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true);
+        mAuthControllerCallback.onEnrollmentsChanged();
+
+        // THEN mConfigured = TRUE
+        assertTrue(triggerSensor.mConfigured);
+
+        // THEN mRegistered = TRUE
+        assertTrue(triggerSensor.mRegistered);
+    }
+
+    @Test
+    public void testGesturesAllInitiallyRespectSettings() {
+        DozeSensors dozeSensors = new DozeSensors(getContext(), mSensorManager, mDozeParameters,
+                mAmbientDisplayConfiguration, mWakeLock, mCallback, mProxCallback, mDozeLog,
+                mProximitySensor, mFakeSettings, mAuthController,
+                mDevicePostureController);
+
+        for (TriggerSensor sensor : dozeSensors.mTriggerSensors) {
+            assertFalse(sensor.mIgnoresSetting);
+        }
+    }
 
     private class TestableDozeSensors extends DozeSensors {
         TestableDozeSensors() {
@@ -407,6 +463,22 @@
                     requiresTouchScreen);
         }
 
+        public TriggerSensor createDozeSensor(
+                Sensor sensor,
+                int pulseReason,
+                boolean configured
+        ) {
+            return new TriggerSensor(/* sensor */ sensor,
+                    /* setting name */ "test_setting",
+                    /* settingDefault */ true,
+                    /* configured */ configured,
+                    /* pulseReason*/ pulseReason,
+                    /* reportsTouchCoordinate*/ false,
+                    /* requiresTouchscreen */ false,
+                    /* ignoresSetting */ false,
+                    /* requiresTouchScreen */false);
+        }
+
         /**
          * create a doze sensor that supports postures and is enabled
          */
@@ -422,6 +494,15 @@
                     /* requiresProx */false,
                     posture);
         }
+
+        public void addSensor(TriggerSensor sensor) {
+            TriggerSensor[] newArray = new TriggerSensor[mTriggerSensors.length + 1];
+            for (int i = 0; i < mTriggerSensors.length; i++) {
+                newArray[i] = mTriggerSensors[i];
+            }
+            newArray[mTriggerSensors.length] = sensor;
+            mTriggerSensors = newArray;
+        }
     }
 
     public static void setSensorType(Sensor sensor, int type, String strType) throws Exception {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.java
similarity index 73%
rename from packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.java
index 6347638..475dde2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagsReleaseTest.java
@@ -25,7 +25,6 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.verifyZeroInteractions;
 
 import android.content.Context;
 
@@ -33,7 +32,6 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.util.settings.SecureSettings;
 
 import org.junit.After;
 import org.junit.Before;
@@ -50,17 +48,16 @@
  * overriding, and should never return any value other than the one provided as the default.
  */
 @SmallTest
-public class FeatureFlagManagerTest extends SysuiTestCase {
-    FeatureFlagManager mFeatureFlagManager;
+public class FeatureFlagsReleaseTest extends SysuiTestCase {
+    FeatureFlagsRelease mFeatureFlagsRelease;
 
-    @Mock private Context mContext;
     @Mock private DumpManager mDumpManager;
 
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
 
-        mFeatureFlagManager = new FeatureFlagManager(mDumpManager);
+        mFeatureFlagsRelease = new FeatureFlagsRelease(mDumpManager);
     }
 
     @After
@@ -71,23 +68,10 @@
     }
 
     @Test
-    public void testIsEnabled() {
-        mFeatureFlagManager.setEnabled(1, true);
-        // Again, nothing changes.
-        assertThat(mFeatureFlagManager.isEnabled(1, false)).isFalse();
-    }
-
-    @Test
     public void testDump() {
-        // Even if a flag is set before
-        mFeatureFlagManager.setEnabled(1, true);
-
         // WHEN the flags have been accessed
-        assertFalse(mFeatureFlagManager.isEnabled(1, false));
-        assertTrue(mFeatureFlagManager.isEnabled(2, true));
-
-        // Even if a flag is set after
-        mFeatureFlagManager.setEnabled(2, false);
+        assertFalse(mFeatureFlagsRelease.isEnabled(1, false));
+        assertTrue(mFeatureFlagsRelease.isEnabled(2, true));
 
         // THEN the dump contains the flags and the default values
         String dump = dumpToString();
@@ -98,7 +82,7 @@
     private String dumpToString() {
         StringWriter sw = new StringWriter();
         PrintWriter pw = new PrintWriter(sw);
-        mFeatureFlagManager.dump(mock(FileDescriptor.class), pw, new String[0]);
+        mFeatureFlagsRelease.dump(mock(FileDescriptor.class), pw, new String[0]);
         pw.flush();
         String dump = sw.toString();
         return dump;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
new file mode 100644
index 0000000..77c837b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/fragments/FragmentServiceTest.kt
@@ -0,0 +1,82 @@
+package com.android.systemui.fragments
+
+import android.app.Fragment
+import android.os.Looper
+import android.test.suitebuilder.annotation.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.qs.QSFragment
+import com.android.systemui.util.mockito.mock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+
+@SmallTest
+class FragmentServiceTest : SysuiTestCase() {
+    private val fragmentCreator = TestFragmentCreator()
+    private val fragmentCreatorFactory = FragmentService.FragmentCreator.Factory { fragmentCreator }
+
+    private lateinit var fragmentService: FragmentService
+
+    @Before
+    fun setUp() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare()
+        }
+
+        fragmentService = FragmentService(fragmentCreatorFactory, mock(), DumpManager())
+    }
+
+    @Test
+    fun constructor_addsFragmentCreatorMethodsToMap() {
+        val map = fragmentService.injectionMap
+        assertThat(map).hasSize(2)
+        assertThat(map.keys).contains(QSFragment::class.java.name)
+        assertThat(map.keys).contains(TestFragmentInCreator::class.java.name)
+    }
+
+    @Test
+    fun addFragmentInstantiationProvider_objectHasNoFragmentMethods_nothingAdded() {
+        fragmentService.addFragmentInstantiationProvider(Object())
+
+        assertThat(fragmentService.injectionMap).hasSize(2)
+    }
+
+    @Test
+    fun addFragmentInstantiationProvider_objectHasFragmentMethods_methodsAdded() {
+        fragmentService.addFragmentInstantiationProvider(
+            @Suppress("unused")
+            object : Any() {
+                fun createTestFragment2() = TestFragment2()
+                fun createTestFragment3() = TestFragment3()
+            }
+        )
+
+        val map = fragmentService.injectionMap
+        assertThat(map).hasSize(4)
+        assertThat(map.keys).contains(TestFragment2::class.java.name)
+        assertThat(map.keys).contains(TestFragment3::class.java.name)
+    }
+
+    @Test
+    fun addFragmentInstantiationProvider_objectFragmentMethodsAlreadyProvided_nothingAdded() {
+        fragmentService.addFragmentInstantiationProvider(
+            @Suppress("unused")
+            object : Any() {
+                fun createTestFragment() = TestFragmentInCreator()
+            }
+        )
+
+        assertThat(fragmentService.injectionMap).hasSize(2)
+    }
+
+    class TestFragmentCreator : FragmentService.FragmentCreator {
+        override fun createQSFragment(): QSFragment = mock()
+        @Suppress("unused")
+        fun createTestFragment(): TestFragmentInCreator = TestFragmentInCreator()
+    }
+
+    class TestFragmentInCreator : Fragment()
+    class TestFragment2 : Fragment()
+    class TestFragment3 : Fragment()
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
index 3b1c5f3..bf5522c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
@@ -54,6 +54,7 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.model.SysUiState;
@@ -115,6 +116,7 @@
     @Mock private UserContextProvider mUserContextProvider;
     @Mock private StatusBar mStatusBar;
     @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    @Mock private DialogLaunchAnimator mDialogLaunchAnimator;
 
     private TestableLooper mTestableLooper;
 
@@ -159,8 +161,8 @@
                 mHandler,
                 mPackageManager,
                 Optional.of(mStatusBar),
-                mKeyguardUpdateMonitor
-        );
+                mKeyguardUpdateMonitor,
+                mDialogLaunchAnimator);
         mGlobalActionsDialogLite.setZeroDialogPressDelayForTesting();
 
         ColorExtractor.GradientColors backdropColors = new ColorExtractor.GradientColors();
@@ -218,7 +220,7 @@
         GlobalActionsDialogLite.ActionsDialogLite dialog = mGlobalActionsDialogLite.createDialog();
 
         GestureDetector.SimpleOnGestureListener gestureListener = spy(dialog.mGestureListener);
-        gestureListener.onSingleTapConfirmed(null);
+        gestureListener.onSingleTapUp(null);
         verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_CLOSE_TAP_OUTSIDE);
     }
 
@@ -444,12 +446,12 @@
 
         // When entering power menu from lockscreen, with smart lock enabled
         when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true);
-        mGlobalActionsDialogLite.showOrHideDialog(true, true);
+        mGlobalActionsDialogLite.showOrHideDialog(true, true, null /* view */);
 
         // Then smart lock will be disabled
         verify(mLockPatternUtils).requireCredentialEntry(eq(user));
 
         // hide dialog again
-        mGlobalActionsDialogLite.showOrHideDialog(true, true);
+        mGlobalActionsDialogLite.showOrHideDialog(true, true, null /* view */);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 6d8645e..b774daf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -41,6 +41,7 @@
 
 import androidx.test.filters.SmallTest;
 
+import com.android.internal.jank.InteractionJankMonitor;
 import com.android.internal.policy.IKeyguardDrawnCallback;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardDisplayManager;
@@ -64,9 +65,6 @@
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
-import java.util.Optional;
-import java.util.function.Function;
-
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -75,6 +73,9 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.Optional;
+import java.util.function.Function;
+
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 @SmallTest
@@ -103,6 +104,7 @@
     private @Mock KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
     private @Mock UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
     private @Mock IKeyguardDrawnCallback mKeyguardDrawnCallback;
+    private @Mock InteractionJankMonitor mInteractionJankMonitor;
     private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
     private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
 
@@ -121,6 +123,8 @@
             .thenReturn(mUnfoldAnimationOptional);
         when(mUnfoldAnimationOptional.isPresent()).thenReturn(true);
         when(mUnfoldAnimationOptional.get()).thenReturn(mUnfoldAnimation);
+        when(mInteractionJankMonitor.begin(any(), anyInt())).thenReturn(true);
+        when(mInteractionJankMonitor.end(anyInt())).thenReturn(true);
 
         mViewMediator = new KeyguardViewMediator(
                 mContext,
@@ -144,7 +148,8 @@
                 mKeyguardStateController,
                 () -> mKeyguardUnlockAnimationController,
                 mUnlockedScreenOffAnimationController,
-                () -> mNotificationShadeDepthController);
+                () -> mNotificationShadeDepthController,
+                mInteractionJankMonitor);
         mViewMediator.start();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
index 175ec87f..a6e567e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt
@@ -104,37 +104,54 @@
     fun testPlayerOrdering() {
         // Test values: key, data, last active time
         val playingLocal = Triple("playing local",
-            DATA.copy(active = true, isPlaying = true, isLocalSession = true, resumption = false),
+            DATA.copy(active = true, isPlaying = true,
+                    playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false),
             4500L)
 
-        val playingRemote = Triple("playing remote",
-            DATA.copy(active = true, isPlaying = true, isLocalSession = false, resumption = false),
+        val playingCast = Triple("playing cast",
+            DATA.copy(active = true, isPlaying = true,
+                    playbackLocation = MediaData.PLAYBACK_CAST_LOCAL, resumption = false),
             5000L)
 
         val pausedLocal = Triple("paused local",
-            DATA.copy(active = true, isPlaying = false, isLocalSession = true, resumption = false),
+            DATA.copy(active = true, isPlaying = false,
+                    playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false),
             1000L)
 
-        val pausedRemote = Triple("paused remote",
-            DATA.copy(active = true, isPlaying = false, isLocalSession = false, resumption = false),
+        val pausedCast = Triple("paused cast",
+            DATA.copy(active = true, isPlaying = false,
+                    playbackLocation = MediaData.PLAYBACK_CAST_LOCAL, resumption = false),
             2000L)
 
+        val playingRcn = Triple("playing RCN",
+            DATA.copy(active = true, isPlaying = true,
+                    playbackLocation = MediaData.PLAYBACK_CAST_REMOTE, resumption = false),
+            5000L)
+
+        val pausedRcn = Triple("paused RCN",
+                DATA.copy(active = true, isPlaying = false,
+                        playbackLocation = MediaData.PLAYBACK_CAST_REMOTE, resumption = false),
+                5000L)
+
         val resume1 = Triple("resume 1",
-            DATA.copy(active = false, isPlaying = false, isLocalSession = true, resumption = true),
+            DATA.copy(active = false, isPlaying = false,
+                    playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = true),
             500L)
 
         val resume2 = Triple("resume 2",
-            DATA.copy(active = false, isPlaying = false, isLocalSession = true, resumption = true),
+            DATA.copy(active = false, isPlaying = false,
+                    playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = true),
             1000L)
 
         // Expected ordering for media players:
         // Actively playing local sessions
-        // Actively playing remote sessions
-        // Paused sessions, by last active
+        // Actively playing cast sessions
+        // Paused local and cast sessions, by last active
+        // RCNs
         // Resume controls, by last active
 
-        val expected = listOf(playingLocal, playingRemote, pausedRemote, pausedLocal, resume2,
-            resume1)
+        val expected = listOf(playingLocal, playingCast, pausedCast, pausedLocal, playingRcn,
+                pausedRcn, resume2, resume1)
 
         expected.forEach {
             clock.setCurrentTimeMillis(it.third)
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 66b6470..f870da3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
@@ -74,8 +74,8 @@
         mManager.addListener(mListener);
 
         mMediaData = new MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null,
-                new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null, true,
-                false, KEY, false, false, false, 0L);
+                new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null,
+                MediaData.PLAYBACK_LOCAL, false, KEY, false, false, false, 0L);
         mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME);
     }
 
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 2b2fc51..f44cc38 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -1,5 +1,6 @@
 package com.android.systemui.media
 
+import android.app.Notification
 import android.app.Notification.MediaStyle
 import android.app.PendingIntent
 import android.app.smartspace.SmartspaceAction
@@ -229,6 +230,30 @@
     }
 
     @Test
+    fun testOnNotificationAdded_isRcn_markedRemote() {
+        val bundle = Bundle().apply {
+            putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, "Remote Cast Notification")
+        }
+        val rcn = SbnBuilder().run {
+            setPkg("com.android.systemui") // System package
+            modifyNotification(context).also {
+                it.setSmallIcon(android.R.drawable.ic_media_pause)
+                it.setStyle(MediaStyle().apply { setMediaSession(session.sessionToken) })
+                it.addExtras(bundle)
+            }
+            build()
+        }
+
+        mediaDataManager.onNotificationAdded(KEY, rcn)
+        assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
+        assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
+        verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true),
+                eq(false))
+        assertThat(mediaDataCaptor.value!!.playbackLocation).isEqualTo(
+                MediaData.PLAYBACK_CAST_REMOTE)
+    }
+
+    @Test
     fun testOnNotificationRemoved_callsListener() {
         mediaDataManager.onNotificationAdded(KEY, mediaNotification)
         mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java))
@@ -306,7 +331,8 @@
         verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true),
                 eq(false))
         val data = mediaDataCaptor.value
-        val dataRemoteWithResume = data.copy(resumeAction = Runnable {}, isLocalSession = false)
+        val dataRemoteWithResume = data.copy(resumeAction = Runnable {},
+                playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
         mediaDataManager.onMediaDataLoaded(KEY, null, dataRemoteWithResume)
 
         // WHEN the notification is removed
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 8dc9eff..421f9be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
@@ -42,7 +42,8 @@
     val mockito = MockitoJUnit.rule()
 
     companion object {
-        val LOCAL = true
+        val LOCAL = MediaData.PLAYBACK_LOCAL
+        val REMOTE = MediaData.PLAYBACK_CAST_LOCAL
         val RESUMPTION = true
         val PLAYING = true
         val UNDETERMINED = null
@@ -58,7 +59,7 @@
         val dataIsPlaying = createMediaData("app1", PLAYING, LOCAL, !RESUMPTION)
 
         val playerIsRemote = mock(MediaControlPanel::class.java)
-        val dataIsRemote = createMediaData("app2", PLAYING, !LOCAL, !RESUMPTION)
+        val dataIsRemote = createMediaData("app2", PLAYING, REMOTE, !RESUMPTION)
 
         MediaPlayerData.addMediaPlayer("2", dataIsRemote, playerIsRemote, systemClock)
         MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying, systemClock)
@@ -100,13 +101,13 @@
         val dataIsPlaying = createMediaData("app1", PLAYING, LOCAL, !RESUMPTION)
 
         val playerIsPlayingAndRemote = mock(MediaControlPanel::class.java)
-        val dataIsPlayingAndRemote = createMediaData("app2", PLAYING, !LOCAL, !RESUMPTION)
+        val dataIsPlayingAndRemote = createMediaData("app2", PLAYING, REMOTE, !RESUMPTION)
 
         val playerIsStoppedAndLocal = mock(MediaControlPanel::class.java)
         val dataIsStoppedAndLocal = createMediaData("app3", !PLAYING, LOCAL, !RESUMPTION)
 
         val playerIsStoppedAndRemote = mock(MediaControlPanel::class.java)
-        val dataIsStoppedAndRemote = createMediaData("app4", !PLAYING, !LOCAL, !RESUMPTION)
+        val dataIsStoppedAndRemote = createMediaData("app4", !PLAYING, REMOTE, !RESUMPTION)
 
         val playerCanResume = mock(MediaControlPanel::class.java)
         val dataCanResume = createMediaData("app5", !PLAYING, LOCAL, RESUMPTION)
@@ -127,8 +128,8 @@
         val players = MediaPlayerData.players()
         assertThat(players).hasSize(6)
         assertThat(players).containsExactly(playerIsPlaying, playerIsPlayingAndRemote,
-            playerIsStoppedAndRemote, playerIsStoppedAndLocal, playerCanResume,
-            playerUndetermined).inOrder()
+            playerIsStoppedAndRemote, playerIsStoppedAndLocal, playerUndetermined,
+            playerCanResume).inOrder()
     }
 
     @Test
@@ -160,9 +161,10 @@
     private fun createMediaData(
         app: String,
         isPlaying: Boolean?,
-        isLocalSession: Boolean,
+        location: Int,
         resumption: Boolean
     ) =
-        MediaData(0, false, 0, app, null, null, null, null, emptyList(), emptyList<Int>(), "",
-            null, null, null, true, null, isLocalSession, resumption, null, false, isPlaying)
+        MediaData(0, false, 0, app, null, null, null, null, emptyList(), emptyList<Int>(),
+            "package:" + app, null, null, null, true, null, location, resumption, "key:" + app,
+            false, isPlaying)
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
index a17a03d..30ee2e4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaResumeListenerTest.kt
@@ -211,10 +211,20 @@
     }
 
     @Test
-    fun testOnLoad_remotePlayback_doesNotCheck() {
-        // When media data is loaded that has not been checked yet, and is not local
-        val dataRemote = data.copy(isLocalSession = false)
-        resumeListener.onMediaDataLoaded(KEY, null, dataRemote)
+    fun testOnLoad_localCast_doesNotCheck() {
+        // When media data is loaded that has not been checked yet, and is a local cast
+        val dataCast = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_LOCAL)
+        resumeListener.onMediaDataLoaded(KEY, null, dataCast)
+
+        // Then we do not take action
+        verify(mediaDataManager, never()).setResumeAction(any(), any())
+    }
+
+    @Test
+    fun testOnload_remoteCast_doesNotCheck() {
+        // When media data is loaded that has not been checked yet, and is a remote cast
+        val dataRcn = data.copy(playbackLocation = MediaData.PLAYBACK_CAST_REMOTE)
+        resumeListener.onMediaDataLoaded(KEY, null, dataRcn)
 
         // Then we do not take action
         verify(mediaDataManager, never()).setResumeAction(any(), any())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 52173c1..1b5e5eb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -121,7 +121,6 @@
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mTitleText.getText()).isEqualTo(mContext.getText(
                 R.string.media_output_dialog_pairing_new));
     }
@@ -139,7 +138,6 @@
         assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_SESSION_NAME);
     }
 
@@ -156,7 +154,6 @@
         assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(mContext.getString(
                 R.string.media_output_dialog_group));
     }
@@ -165,14 +162,13 @@
     public void onBindViewHolder_bindConnectedDevice_verifyView() {
         mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
 
-        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
         assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
     }
 
     @Test
@@ -199,7 +195,6 @@
         assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_2);
     }
@@ -213,13 +208,10 @@
 
         assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
+        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(
                 TEST_DEVICE_NAME_2);
-        assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(
-                mContext.getString(R.string.media_output_dialog_disconnected));
+        assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
@@ -233,7 +225,6 @@
         assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mSubTitleText.getText()).isEqualTo(mContext.getText(
@@ -248,14 +239,13 @@
                 LocalMediaManager.MediaDeviceState.STATE_CONNECTING);
         mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
 
-        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
         assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(mViewHolder.mTwoLineTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
+        assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
@@ -268,7 +258,6 @@
         assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mTitleText.getText()).isEqualTo(TEST_DEVICE_NAME_1);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 053851e..4dac6d5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.graphics.drawable.Drawable;
 import android.media.session.MediaSessionManager;
 import android.os.Bundle;
 import android.testing.AndroidTestingRunner;
@@ -70,6 +71,7 @@
     private MediaOutputController mMediaOutputController;
     private int mHeaderIconRes;
     private IconCompat mIconCompat;
+    private Drawable mAppSourceDrawable;
     private CharSequence mHeaderTitle;
     private CharSequence mHeaderSubtitle;
 
@@ -173,6 +175,11 @@
         }
 
         @Override
+        Drawable getAppSourceIcon() {
+            return mAppSourceDrawable;
+        }
+
+        @Override
         int getHeaderIconRes() {
             return mHeaderIconRes;
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index f7e60ca..d71d98e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -19,6 +19,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -234,7 +235,7 @@
 
         mMediaOutputController.onRequestFailed(0 /* reason */);
 
-        verify(mCb).onRouteChanged();
+        verify(mCb, atLeastOnce()).onRouteChanged();
     }
 
     @Test
@@ -469,7 +470,7 @@
         when(entry.getSbn()).thenReturn(sbn);
         when(sbn.getNotification()).thenReturn(notification);
         when(sbn.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
-        when(notification.hasMediaSession()).thenReturn(true);
+        when(notification.isMediaNotification()).thenReturn(true);
         when(notification.getLargeIcon()).thenReturn(null);
 
         assertThat(mMediaOutputController.getNotificationIcon()).isNull();
@@ -489,7 +490,7 @@
         when(entry.getSbn()).thenReturn(sbn);
         when(sbn.getNotification()).thenReturn(notification);
         when(sbn.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
-        when(notification.hasMediaSession()).thenReturn(true);
+        when(notification.isMediaNotification()).thenReturn(true);
         when(notification.getLargeIcon()).thenReturn(icon);
 
         assertThat(mMediaOutputController.getNotificationIcon() instanceof IconCompat).isTrue();
@@ -509,7 +510,7 @@
         when(entry.getSbn()).thenReturn(sbn);
         when(sbn.getNotification()).thenReturn(notification);
         when(sbn.getPackageName()).thenReturn(TEST_PACKAGE_NAME);
-        when(notification.hasMediaSession()).thenReturn(false);
+        when(notification.isMediaNotification()).thenReturn(false);
         when(notification.getLargeIcon()).thenReturn(icon);
 
         assertThat(mMediaOutputController.getNotificationIcon()).isNull();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java
index ca5d570..2c883a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupAdapterTest.java
@@ -100,7 +100,6 @@
         assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mGroupViewHolder.mTwoLineTitleText.getText()).isEqualTo(mContext.getText(
@@ -114,7 +113,6 @@
         assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -140,7 +138,6 @@
         assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -165,7 +162,6 @@
         assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
@@ -183,7 +179,6 @@
         assertThat(mGroupViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mGroupViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mGroupViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mGroupViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttChipControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttChipControllerTest.kt
new file mode 100644
index 0000000..efb4931
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttChipControllerTest.kt
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2021 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.taptotransfer
+
+import android.view.WindowManager
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.commandline.Command
+import com.android.systemui.statusbar.commandline.CommandRegistry
+import com.android.systemui.util.mockito.any
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import java.io.PrintWriter
+import java.io.StringWriter
+import java.util.concurrent.Executor
+
+@SmallTest
+class MediaTttChipControllerTest : SysuiTestCase() {
+
+    private lateinit var mediaTttChipController: MediaTttChipController
+
+    private val inlineExecutor = Executor { command -> command.run() }
+    private val commandRegistry = CommandRegistry(context, inlineExecutor)
+    private val pw = PrintWriter(StringWriter())
+
+    @Mock
+    private lateinit var windowManager: WindowManager
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        mediaTttChipController = MediaTttChipController(context, commandRegistry, windowManager)
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun constructor_addCommmandAlreadyRegistered() {
+        // Since creating the chip controller should automatically register the add command, it
+        // should throw when registering it again.
+        commandRegistry.registerCommand(
+            MediaTttChipController.ADD_CHIP_COMMAND_TAG
+        ) { EmptyCommand() }
+    }
+
+    @Test(expected = IllegalStateException::class)
+    fun constructor_removeCommmandAlreadyRegistered() {
+        // Since creating the chip controller should automatically register the remove command, it
+        // should throw when registering it again.
+        commandRegistry.registerCommand(
+            MediaTttChipController.REMOVE_CHIP_COMMAND_TAG
+        ) { EmptyCommand() }
+    }
+
+    @Test
+    fun addChipCommand_chipAdded() {
+        commandRegistry.onShellCommand(pw, arrayOf(MediaTttChipController.ADD_CHIP_COMMAND_TAG))
+
+        verify(windowManager).addView(any(), any())
+    }
+
+    @Test
+    fun addChipCommand_twice_chipNotAddedTwice() {
+        commandRegistry.onShellCommand(pw, arrayOf(MediaTttChipController.ADD_CHIP_COMMAND_TAG))
+        reset(windowManager)
+
+        commandRegistry.onShellCommand(pw, arrayOf(MediaTttChipController.ADD_CHIP_COMMAND_TAG))
+        verify(windowManager, never()).addView(any(), any())
+    }
+
+    @Test
+    fun removeChipCommand_chipRemoved() {
+        // First, add the chip
+        commandRegistry.onShellCommand(pw, arrayOf(MediaTttChipController.ADD_CHIP_COMMAND_TAG))
+
+        // Then, remove it
+        commandRegistry.onShellCommand(pw, arrayOf(MediaTttChipController.REMOVE_CHIP_COMMAND_TAG))
+
+        verify(windowManager).removeView(any())
+    }
+
+    @Test
+    fun removeChipCommand_noAdd_viewNotRemoved() {
+        commandRegistry.onShellCommand(pw, arrayOf(MediaTttChipController.REMOVE_CHIP_COMMAND_TAG))
+
+        verify(windowManager, never()).removeView(any())
+    }
+
+    class EmptyCommand : Command {
+        override fun execute(pw: PrintWriter, args: List<String>) {
+        }
+
+        override fun help(pw: PrintWriter) {
+        }
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
new file mode 100644
index 0000000..a445d6f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavBarHelperTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2021 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.navigationbar;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+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.content.ComponentName;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.accessibility.AccessibilityButtonModeObserver;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Optional;
+
+import dagger.Lazy;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class NavBarHelperTest extends SysuiTestCase {
+
+    @Mock
+    AccessibilityManager mAccessibilityManager;
+    @Mock
+    AccessibilityManagerWrapper mAccessibilityManagerWrapper;
+    @Mock
+    AccessibilityButtonModeObserver mAccessibilityButtonModeObserver;
+    @Mock
+    OverviewProxyService mOverviewProxyService;
+    @Mock
+    Lazy<AssistManager> mAssistManagerLazy;
+    @Mock
+    AssistManager mAssistManager;
+    @Mock
+    NavigationModeController mNavigationModeController;
+    @Mock
+    UserTracker mUserTracker;
+    @Mock
+    ComponentName mAssistantComponent;
+    @Mock
+    DumpManager mDumpManager;
+    @Mock
+    NavBarHelper.NavbarTaskbarStateUpdater mNavbarTaskbarStateUpdater;
+
+    private NavBarHelper mNavBarHelper;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+        when(mAssistManagerLazy.get()).thenReturn(mAssistManager);
+        when(mAssistManager.getAssistInfoForUser(anyInt())).thenReturn(mAssistantComponent);
+        when(mUserTracker.getUserId()).thenReturn(1);
+
+        mNavBarHelper = new NavBarHelper(mContext, mAccessibilityManager,
+                mAccessibilityManagerWrapper, mAccessibilityButtonModeObserver,
+                mOverviewProxyService, mAssistManagerLazy, () -> Optional.of(mock(StatusBar.class)),
+                mNavigationModeController, mUserTracker, mDumpManager);
+
+    }
+
+    @Test
+    public void registerListenersInCtor() {
+        verify(mAccessibilityButtonModeObserver, times(1)).addListener(mNavBarHelper);
+        verify(mNavigationModeController, times(1)).addListener(mNavBarHelper);
+        verify(mOverviewProxyService, times(1)).addCallback(mNavBarHelper);
+    }
+
+    @Test
+    public void registerAssistantContentObserver() {
+        mNavBarHelper.init();
+        verify(mAssistManager, times(1)).getAssistInfoForUser(anyInt());
+    }
+
+    @Test
+    public void callbacksFiredWhenRegistering() {
+        mNavBarHelper.init();
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+        verify(mNavbarTaskbarStateUpdater, times(1))
+                .updateAccessibilityServicesState();
+        verify(mNavbarTaskbarStateUpdater, times(1))
+                .updateAssistantAvailable(anyBoolean());
+    }
+
+    @Test
+    public void assistantCallbacksFiredAfterConnecting() {
+        mNavBarHelper.init();
+        // 1st set of callbacks get called when registering
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+
+        mNavBarHelper.onConnectionChanged(false);
+        // assert no more callbacks fired
+        verify(mNavbarTaskbarStateUpdater, times(1))
+                .updateAccessibilityServicesState();
+        verify(mNavbarTaskbarStateUpdater, times(1))
+                .updateAssistantAvailable(anyBoolean());
+
+        mNavBarHelper.onConnectionChanged(true);
+        // assert no more callbacks fired
+        verify(mNavbarTaskbarStateUpdater, times(1))
+                .updateAccessibilityServicesState();
+        verify(mNavbarTaskbarStateUpdater, times(2))
+                .updateAssistantAvailable(anyBoolean());
+    }
+
+    @Test
+    public void a11yCallbacksFiredAfterModeChange() {
+        mNavBarHelper.init();
+        // 1st set of callbacks get called when registering
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+
+        mNavBarHelper.onAccessibilityButtonModeChanged(0);
+        verify(mNavbarTaskbarStateUpdater, times(2))
+                .updateAccessibilityServicesState();
+        verify(mNavbarTaskbarStateUpdater, times(1))
+                .updateAssistantAvailable(anyBoolean());
+    }
+
+    @Test
+    public void assistantCallbacksFiredAfterNavModeChange() {
+        mNavBarHelper.init();
+        // 1st set of callbacks get called when registering
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+
+        mNavBarHelper.onNavigationModeChanged(0);
+        verify(mNavbarTaskbarStateUpdater, times(1))
+                .updateAccessibilityServicesState();
+        verify(mNavbarTaskbarStateUpdater, times(2))
+                .updateAssistantAvailable(anyBoolean());
+    }
+
+    @Test
+    public void removeListenerNoCallbacksFired() {
+        mNavBarHelper.init();
+        // 1st set of callbacks get called when registering
+        mNavBarHelper.registerNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+
+        // Remove listener
+        mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater);
+
+        // Would have fired 2nd callback if not removed
+        mNavBarHelper.onAccessibilityButtonModeChanged(0);
+
+        // assert no more callbacks fired
+        verify(mNavbarTaskbarStateUpdater, times(1))
+                .updateAccessibilityServicesState();
+        verify(mNavbarTaskbarStateUpdater, times(1))
+                .updateAssistantAvailable(anyBoolean());
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
index 4fc329f..9d2541c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarControllerTest.java
@@ -45,6 +45,7 @@
 import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.LightBarController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 
 import org.junit.After;
@@ -82,11 +83,12 @@
                         mCommandQueue,
                         Dependency.get(Dependency.MAIN_HANDLER),
                         mock(ConfigurationController.class),
-                        mock(NavigationBarA11yHelper.class),
+                        mock(NavBarHelper.class),
                         mock(TaskbarDelegate.class),
                         mNavigationBarFactory,
                         mock(DumpManager.class),
-                        mock(AutoHideController.class)));
+                        mock(AutoHideController.class),
+                        mock(LightBarController.class)));
         initializeNavigationBars();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
index 223ffbd..5003013 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/NavigationBarTest.java
@@ -23,17 +23,20 @@
 import static android.inputmethodservice.InputMethodService.IME_VISIBLE;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
+import static android.view.WindowInsets.Type.ime;
 
 import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.HOME_BUTTON_LONG_PRESS_DURATION_MS;
 import static com.android.systemui.navigationbar.NavigationBar.NavBarActionEvent.NAVBAR_ASSIST_LONGPRESS;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -57,6 +60,7 @@
 import android.view.DisplayInfo;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.WindowMetrics;
 import android.view.accessibility.AccessibilityManager;
@@ -72,6 +76,7 @@
 import com.android.systemui.accessibility.SystemActions;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dump.DumpManager;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.navigationbar.gestural.EdgeBackGestureHandler;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -83,8 +88,10 @@
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.utils.leaks.LeakCheckedTest;
@@ -98,6 +105,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
 
 import java.util.Optional;
 
@@ -130,8 +138,7 @@
     EdgeBackGestureHandler.Factory mEdgeBackGestureHandlerFactory;
     @Mock
     EdgeBackGestureHandler mEdgeBackGestureHandler;
-    @Mock
-    NavigationBarA11yHelper mNavigationBarA11yHelper;
+    NavBarHelper mNavBarHelper;
     @Mock
     private LightBarController mLightBarController;
     @Mock
@@ -148,6 +155,8 @@
     private InputMethodManager mInputMethodManager;
     @Mock
     private AssistManager mAssistManager;
+    @Mock
+    private StatusBar mStatusBar;
 
     @Rule
     public final LeakCheckedTest.SysuiLeakCheck mLeakCheck = new LeakCheckedTest.SysuiLeakCheck();
@@ -172,6 +181,12 @@
         mDependency.injectTestDependency(OverviewProxyService.class, mOverviewProxyService);
         mDependency.injectTestDependency(NavigationModeController.class, mNavigationModeController);
         TestableLooper.get(this).runWithLooper(() -> {
+            mNavBarHelper = spy(new NavBarHelper(mContext, mock(AccessibilityManager.class),
+                    mock(AccessibilityManagerWrapper.class),
+                    mock(AccessibilityButtonModeObserver.class), mOverviewProxyService,
+                    () -> mock(AssistManager.class), () -> Optional.of(mStatusBar),
+                    mock(NavigationModeController.class), mock(UserTracker.class),
+                    mock(DumpManager.class)));
             mNavigationBar = createNavBar(mContext);
             mExternalDisplayNavigationBar = createNavBar(mSysuiTestableContextExternal);
         });
@@ -220,6 +235,7 @@
                 new DeviceConfig.Properties.Builder(DeviceConfig.NAMESPACE_SYSTEMUI)
                     .setLong(HOME_BUTTON_LONG_PRESS_DURATION_MS, 100)
                     .build());
+        when(mNavBarHelper.getLongPressHomeEnabled()).thenReturn(true);
         mNavigationBar.onViewAttachedToWindow(mNavigationBar.createView(null));
 
         mNavigationBar.onHomeTouch(mNavigationBar.getView(), MotionEvent.obtain(
@@ -255,6 +271,11 @@
         // Create default & external NavBar fragment.
         NavigationBar defaultNavBar = mNavigationBar;
         NavigationBar externalNavBar = mExternalDisplayNavigationBar;
+        NotificationShadeWindowView mockShadeWindowView = mock(NotificationShadeWindowView.class);
+        WindowInsets windowInsets = new WindowInsets.Builder().setVisible(ime(), false).build();
+        doReturn(windowInsets).when(mockShadeWindowView).getRootWindowInsets();
+        doReturn(mockShadeWindowView).when(mStatusBar).getNotificationShadeWindowView();
+        doReturn(true).when(mockShadeWindowView).isAttachedToWindow();
         doNothing().when(defaultNavBar).checkNavBarModes();
         doNothing().when(externalNavBar).checkNavBarModes();
         defaultNavBar.createView(null);
@@ -281,17 +302,51 @@
     }
 
     @Test
+    public void testSetImeWindowStatusWhenKeyguardLockingAndImeInsetsChange() {
+        NotificationShadeWindowView mockShadeWindowView = mock(NotificationShadeWindowView.class);
+        doReturn(mockShadeWindowView).when(mStatusBar).getNotificationShadeWindowView();
+        doReturn(true).when(mockShadeWindowView).isAttachedToWindow();
+        doNothing().when(mNavigationBar).checkNavBarModes();
+        mNavigationBar.createView(null);
+        WindowInsets windowInsets = new WindowInsets.Builder().setVisible(ime(), false).build();
+        doReturn(windowInsets).when(mockShadeWindowView).getRootWindowInsets();
+
+        // Verify navbar altered back icon when an app is showing IME
+        mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE,
+                BACK_DISPOSITION_DEFAULT, true);
+        assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
+        assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
+
+        // Verify navbar didn't alter and showing back icon when the keyguard is showing without
+        // requesting IME insets visible.
+        doReturn(true).when(mStatusBar).isKeyguardShowing();
+        mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE,
+                BACK_DISPOSITION_DEFAULT, true);
+        assertFalse((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
+        assertFalse((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
+
+        // Verify navbar altered and showing back icon when the keyguard is showing and
+        // requesting IME insets visible.
+        windowInsets = new WindowInsets.Builder().setVisible(ime(), true).build();
+        doReturn(windowInsets).when(mockShadeWindowView).getRootWindowInsets();
+        mNavigationBar.setImeWindowStatus(DEFAULT_DISPLAY, null, IME_VISIBLE,
+                BACK_DISPOSITION_DEFAULT, true);
+        assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_BACK_ALT) != 0);
+        assertTrue((mNavigationBar.getNavigationIconHints() & NAVIGATION_HINT_IME_SHOWN) != 0);
+    }
+
+    @Test
     public void testA11yEventAfterDetach() {
         View v = mNavigationBar.createView(null);
         mNavigationBar.onViewAttachedToWindow(v);
-        verify(mNavigationBarA11yHelper).registerA11yEventListener(any(
-                NavigationBarA11yHelper.NavA11yEventListener.class));
+        verify(mNavBarHelper).registerNavTaskStateUpdater(any(
+                NavBarHelper.NavbarTaskbarStateUpdater.class));
         mNavigationBar.onViewDetachedFromWindow(v);
-        verify(mNavigationBarA11yHelper).removeA11yEventListener(any(
-                NavigationBarA11yHelper.NavA11yEventListener.class));
+        verify(mNavBarHelper).removeNavTaskStateUpdater(any(
+                NavBarHelper.NavbarTaskbarStateUpdater.class));
 
         // Should be safe even though the internal view is now null.
-        mNavigationBar.updateAccessibilityServicesState();
+        mNavigationBar.updateAcessibilityStateFlags();
     }
 
     private NavigationBar createNavBar(Context context) {
@@ -313,7 +368,7 @@
                 Optional.of(mock(Pip.class)),
                 Optional.of(mock(LegacySplitScreen.class)),
                 Optional.of(mock(Recents.class)),
-                () -> Optional.of(mock(StatusBar.class)),
+                () -> Optional.of(mStatusBar),
                 mock(ShadeController.class),
                 mock(NotificationRemoteInputManager.class),
                 mock(NotificationShadeDepthController.class),
@@ -321,7 +376,7 @@
                 mHandler,
                 mock(NavigationBarOverlayController.class),
                 mUiEventLogger,
-                mNavigationBarA11yHelper,
+                mNavBarHelper,
                 mock(UserTracker.class),
                 mLightBarController,
                 mLightBarcontrollerFactory,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
index d2bba36..26f04fc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/FooterActionsControllerTest.kt
@@ -1,6 +1,8 @@
 package com.android.systemui.qs
 
+import android.os.Handler
 import android.os.UserManager
+import android.provider.Settings
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
 import android.testing.ViewUtils
@@ -16,10 +18,12 @@
 import com.android.systemui.globalactions.GlobalActionsDialogLite
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.qs.FooterActionsController.ExpansionState
+import com.android.systemui.settings.UserTracker
 import com.android.systemui.statusbar.phone.MultiUserSwitchController
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.statusbar.policy.UserInfoController
 import com.android.systemui.tuner.TunerService
+import com.android.systemui.util.settings.FakeSettings
 import com.android.systemui.utils.leaks.FakeTunerService
 import com.android.systemui.utils.leaks.LeakCheckedTest
 import com.google.common.truth.Truth.assertThat
@@ -42,6 +46,8 @@
     @Mock
     private lateinit var userManager: UserManager
     @Mock
+    private lateinit var userTracker: UserTracker
+    @Mock
     private lateinit var activityStarter: ActivityStarter
     @Mock
     private lateinit var deviceProvisionedController: DeviceProvisionedController
@@ -62,11 +68,13 @@
     private lateinit var view: FooterActionsView
     private val falsingManager: FalsingManagerFake = FalsingManagerFake()
     private lateinit var testableLooper: TestableLooper
+    private lateinit var fakeSettings: FakeSettings
 
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
         testableLooper = TestableLooper.get(this)
+        fakeSettings = FakeSettings()
         injectLeakCheckedDependencies(*LeakCheckedTest.ALL_SUPPORTED_CLASSES)
         val fakeTunerService = Dependency.get(TunerService::class.java) as FakeTunerService
 
@@ -74,10 +82,11 @@
                 .inflate(R.layout.footer_actions, null) as FooterActionsView
 
         controller = FooterActionsController(view, qsPanelController, activityStarter,
-                userManager, userInfoController, multiUserSwitchController,
+                userManager, userTracker, userInfoController, multiUserSwitchController,
                 deviceProvisionedController, falsingManager, metricsLogger, fakeTunerService,
                 globalActionsDialog, uiEventLogger, showPMLiteButton = true,
-                buttonsVisibleState = ExpansionState.EXPANDED)
+                buttonsVisibleState = ExpansionState.EXPANDED, fakeSettings,
+                Handler(testableLooper.looper))
         controller.init()
         ViewUtils.attachView(view)
         // View looper is the testable looper associated with the test
@@ -122,4 +131,24 @@
 
         assertThat(multiUserSwitch.visibility).isEqualTo(View.VISIBLE)
     }
+
+    @Test
+    fun testMultiUserSwitchUpdatedWhenSettingChanged() {
+        // When expanded, listening is true
+        controller.setListening(true)
+        testableLooper.processAllMessages()
+
+        val multiUserSwitch = view.requireViewById<View>(R.id.multi_user_switch)
+        assertThat(multiUserSwitch.visibility).isNotEqualTo(View.VISIBLE)
+
+        // The setting is only used as an indicator for whether the view should refresh. The actual
+        // value of the setting is ignored; isMultiUserEnabled is the source of truth
+        whenever(multiUserSwitchController.isMultiUserEnabled).thenReturn(true)
+
+        // Changing the value of USER_SWITCHER_ENABLED should cause the view to update
+        fakeSettings.putIntForUser(Settings.Global.USER_SWITCHER_ENABLED, 1, userTracker.userId)
+        testableLooper.processAllMessages()
+
+        assertThat(multiUserSwitch.visibility).isEqualTo(View.VISIBLE)
+    }
 }
\ No newline at end of file
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 047ff037..c1562c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -54,6 +54,7 @@
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.connectivity.StatusBarFlags;
 import com.android.systemui.statusbar.phone.AutoTileManager;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -101,6 +102,8 @@
     private TileServiceRequestController mTileServiceRequestController;
     @Mock
     private FeatureFlags mFeatureFlags;
+    @Mock
+    private StatusBarFlags mStatusBarFlags;
 
     public QSFragmentTest() {
         super(QSFragment.class);
@@ -146,7 +149,7 @@
                 mock(BroadcastDispatcher.class), Optional.of(mock(StatusBar.class)),
                 mock(QSLogger.class), mock(UiEventLogger.class), mock(UserTracker.class),
                 mock(SecureSettings.class), mock(CustomTileStatePersister.class),
-                mTileServiceRequestControllerBuilder, mFeatureFlags);
+                mTileServiceRequestControllerBuilder, mFeatureFlags, mStatusBarFlags);
         qs.setHost(host);
 
         qs.setListening(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt
index f41d7b1..e2a0626 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt
@@ -1,7 +1,6 @@
 package com.android.systemui.qs
 
 import android.testing.AndroidTestingRunner
-import android.view.ViewGroup
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
 import org.junit.Before
@@ -9,7 +8,6 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
-import org.mockito.Mockito.`when`
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.junit.MockitoJUnit
@@ -18,13 +16,9 @@
 @SmallTest
 class QSSquishinessControllerTest : SysuiTestCase() {
 
-    @Mock private lateinit var qqsFooterActionsView: FooterActionsView
-    @Mock private lateinit var qqsFooterActionsViewLP: ViewGroup.MarginLayoutParams
     @Mock private lateinit var qsAnimator: QSAnimator
     @Mock private lateinit var qsPanelController: QSPanelController
     @Mock private lateinit var quickQsPanelController: QuickQSPanelController
-    @Mock private lateinit var tileLayout: TileLayout
-    @Mock private lateinit var pagedTileLayout: PagedTileLayout
 
     @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
 
@@ -32,11 +26,8 @@
 
     @Before
     fun setup() {
-        qsSquishinessController = QSSquishinessController(qqsFooterActionsView, qsAnimator,
+        qsSquishinessController = QSSquishinessController(qsAnimator,
                 qsPanelController, quickQsPanelController)
-        `when`(quickQsPanelController.tileLayout).thenReturn(tileLayout)
-        `when`(qsPanelController.tileLayout).thenReturn(pagedTileLayout)
-        `when`(qqsFooterActionsView.layoutParams).thenReturn(qqsFooterActionsViewLP)
     }
 
     @Test
@@ -51,7 +42,7 @@
     @Test
     fun setSquishiness_updatesTiles() {
         qsSquishinessController.squishiness = 0.5f
-        verify(tileLayout).setSquishinessFraction(0.5f)
-        verify(pagedTileLayout).setSquishinessFraction(0.5f)
+        verify(qsPanelController).setSquishinessFraction(0.5f)
+        verify(quickQsPanelController).setSquishinessFraction(0.5f)
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index aba043b..913b1d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -63,6 +63,7 @@
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.connectivity.StatusBarFlags;
 import com.android.systemui.statusbar.phone.AutoTileManager;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -129,6 +130,8 @@
     private TileServiceRequestController mTileServiceRequestController;
     @Mock
     private FeatureFlags mFeatureFlags;
+    @Mock
+    private StatusBarFlags mStatusBarFlags;
 
     private Handler mHandler;
     private TestableLooper mLooper;
@@ -149,9 +152,9 @@
                 mLooper.getLooper(), mPluginManager, mTunerService, mAutoTiles, mDumpManager,
                 mBroadcastDispatcher, mStatusBar, mQSLogger, mUiEventLogger, mUserTracker,
                 mSecureSettings, mCustomTileStatePersister, mTileServiceRequestControllerBuilder,
-                mFeatureFlags);
+                mFeatureFlags, mStatusBarFlags);
         setUpTileFactory();
-        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(false);
+        when(mStatusBarFlags.isProviderModelSettingEnabled()).thenReturn(false);
     }
 
     private void setUpTileFactory() {
@@ -179,13 +182,13 @@
 
     @Test
     public void testLoadTileSpecs_emptySetting() {
-        List<String> tiles = QSTileHost.loadTileSpecs(mContext, "", mFeatureFlags);
+        List<String> tiles = QSTileHost.loadTileSpecs(mContext, "", mStatusBarFlags);
         assertFalse(tiles.isEmpty());
     }
 
     @Test
     public void testLoadTileSpecs_nullSetting() {
-        List<String> tiles = QSTileHost.loadTileSpecs(mContext, null, mFeatureFlags);
+        List<String> tiles = QSTileHost.loadTileSpecs(mContext, null, mStatusBarFlags);
         assertFalse(tiles.isEmpty());
     }
 
@@ -200,7 +203,7 @@
 
     @Test
     public void testRemoveWifiAndCellularWithoutInternet() {
-        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+        when(mStatusBarFlags.isProviderModelSettingEnabled()).thenReturn(true);
         mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2");
 
         assertEquals("internet", mQSTileHost.mTileSpecs.get(0));
@@ -210,7 +213,7 @@
 
     @Test
     public void testRemoveWifiAndCellularWithInternet() {
-        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+        when(mStatusBarFlags.isProviderModelSettingEnabled()).thenReturn(true);
         mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "wifi, spec1, cell, spec2, internet");
 
         assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
@@ -220,7 +223,7 @@
 
     @Test
     public void testRemoveWifiWithoutInternet() {
-        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+        when(mStatusBarFlags.isProviderModelSettingEnabled()).thenReturn(true);
         mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, wifi, spec2");
 
         assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
@@ -230,7 +233,7 @@
 
     @Test
     public void testRemoveCellWithInternet() {
-        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+        when(mStatusBarFlags.isProviderModelSettingEnabled()).thenReturn(true);
         mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1, spec2, cell, internet");
 
         assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
@@ -240,7 +243,7 @@
 
     @Test
     public void testNoWifiNoCellularNoInternet() {
-        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+        when(mStatusBarFlags.isProviderModelSettingEnabled()).thenReturn(true);
         mQSTileHost.onTuningChanged(QSTileHost.TILES_SETTING, "spec1,spec2");
 
         assertEquals("spec1", mQSTileHost.mTileSpecs.get(0));
@@ -380,7 +383,7 @@
 
     @Test
     public void testLoadTileSpec_repeated() {
-        List<String> specs = QSTileHost.loadTileSpecs(mContext, "spec1,spec1,spec2", mFeatureFlags);
+        List<String> specs = QSTileHost.loadTileSpecs(mContext, "spec1,spec1,spec2", mStatusBarFlags);
 
         assertEquals(2, specs.size());
         assertEquals("spec1", specs.get(0));
@@ -391,7 +394,7 @@
     public void testLoadTileSpec_repeatedInDefault() {
         mContext.getOrCreateTestableResources()
                 .addOverride(R.string.quick_settings_tiles_default, "spec1,spec1");
-        List<String> specs = QSTileHost.loadTileSpecs(mContext, "default", mFeatureFlags);
+        List<String> specs = QSTileHost.loadTileSpecs(mContext, "default", mStatusBarFlags);
 
         // Remove spurious tiles, like dbg:mem
         specs.removeIf(spec -> !"spec1".equals(spec));
@@ -402,7 +405,7 @@
     public void testLoadTileSpec_repeatedDefaultAndSetting() {
         mContext.getOrCreateTestableResources()
                 .addOverride(R.string.quick_settings_tiles_default, "spec1");
-        List<String> specs = QSTileHost.loadTileSpecs(mContext, "default,spec1", mFeatureFlags);
+        List<String> specs = QSTileHost.loadTileSpecs(mContext, "default,spec1", mStatusBarFlags);
 
         // Remove spurious tiles, like dbg:mem
         specs.removeIf(spec -> !"spec1".equals(spec));
@@ -442,11 +445,12 @@
                 UiEventLogger uiEventLogger, UserTracker userTracker,
                 SecureSettings secureSettings, CustomTileStatePersister customTileStatePersister,
                 TileServiceRequestController.Builder tileServiceRequestControllerBuilder,
-                FeatureFlags featureFlags) {
+                FeatureFlags featureFlags, StatusBarFlags statusBarFlags) {
             super(context, iconController, defaultFactory, mainHandler, bgLooper, pluginManager,
                     tunerService, autoTiles, dumpManager, broadcastDispatcher,
                     Optional.of(statusBar), qsLogger, uiEventLogger, userTracker, secureSettings,
-                    customTileStatePersister, tileServiceRequestControllerBuilder, featureFlags);
+                    customTileStatePersister, tileServiceRequestControllerBuilder, featureFlags,
+                    statusBarFlags);
         }
 
         @Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
index 3625874..815c818 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickStatusBarHeaderControllerTest.kt
@@ -27,6 +27,7 @@
 import com.android.systemui.colorextraction.SysuiColorExtractor
 import com.android.systemui.demomode.DemoModeController
 import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.privacy.OngoingPrivacyChip
 import com.android.systemui.privacy.PrivacyDialogController
@@ -248,7 +249,7 @@
 
     @Test
     fun testRSSISlot_notCombined() {
-        `when`(featureFlags.isCombinedStatusBarSignalIconsEnabled).thenReturn(false)
+        `when`(featureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)).thenReturn(false)
         controller.init()
 
         val captor = argumentCaptor<List<String>>()
@@ -261,7 +262,7 @@
 
     @Test
     fun testRSSISlot_combined() {
-        `when`(featureFlags.isCombinedStatusBarSignalIconsEnabled).thenReturn(true)
+        `when`(featureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)).thenReturn(true)
         controller.init()
 
         val captor = argumentCaptor<List<String>>()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/SecureSettingTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/SettingObserverTest.kt
similarity index 96%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/SecureSettingTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/qs/SettingObserverTest.kt
index 6af8402..4be6890 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/SecureSettingTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/SettingObserverTest.kt
@@ -35,7 +35,7 @@
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
 @TestableLooper.RunWithLooper
-class SecureSettingTest : SysuiTestCase() {
+class SettingObserverTest : SysuiTestCase() {
 
     companion object {
         private const val TEST_SETTING = "setting"
@@ -46,7 +46,7 @@
     }
 
     private lateinit var testableLooper: TestableLooper
-    private lateinit var setting: SecureSetting
+    private lateinit var setting: SettingObserver
     private lateinit var secureSettings: SecureSettings
 
     private lateinit var callback: Callback
@@ -56,7 +56,7 @@
         testableLooper = TestableLooper.get(this)
         secureSettings = FakeSettings()
 
-        setting = object : SecureSetting(
+        setting = object : SettingObserver(
                 secureSettings,
                 Handler(testableLooper.looper),
                 TEST_SETTING,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
index 018806e..c3a488f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/customize/TileQueryHelperTest.java
@@ -53,12 +53,12 @@
 import com.android.internal.logging.InstanceId;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.plugins.qs.QSIconView;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.settings.UserTracker;
+import com.android.systemui.statusbar.connectivity.StatusBarFlags;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -110,7 +110,7 @@
     @Mock
     private UserTracker mUserTracker;
     @Mock
-    private FeatureFlags mFeatureFlags;
+    private StatusBarFlags mStatusBarFlags;
     @Captor
     private ArgumentCaptor<List<TileQueryHelper.TileInfo>> mCaptor;
 
@@ -136,12 +136,12 @@
                     }
                 }
         ).when(mQSTileHost).createTile(anyString());
-        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(false);
+        when(mStatusBarFlags.isProviderModelSettingEnabled()).thenReturn(false);
         FakeSystemClock clock = new FakeSystemClock();
         mMainExecutor = new FakeExecutor(clock);
         mBgExecutor = new FakeExecutor(clock);
         mTileQueryHelper = new TileQueryHelper(
-                mContext, mUserTracker, mMainExecutor, mBgExecutor, mFeatureFlags);
+                mContext, mUserTracker, mMainExecutor, mBgExecutor, mStatusBarFlags);
         mTileQueryHelper.setListener(mListener);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
index e756b7d..29b3b86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/external/TileServicesTest.java
@@ -51,6 +51,7 @@
 import com.android.systemui.qs.tileimpl.QSFactoryImpl;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.connectivity.StatusBarFlags;
 import com.android.systemui.statusbar.phone.AutoTileManager;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
@@ -107,6 +108,8 @@
     private TileServiceRequestController mTileServiceRequestController;
     @Mock
     private FeatureFlags mFeatureFlags;
+    @Mock
+    private StatusBarFlags mStatusBarFlags;
 
     @Before
     public void setUp() throws Exception {
@@ -134,7 +137,8 @@
                 mSecureSettings,
                 mock(CustomTileStatePersister.class),
                 mTileServiceRequestControllerBuilder,
-                mFeatureFlags);
+                mFeatureFlags,
+                mStatusBarFlags);
         mTileService = new TestTileServices(host, Looper.getMainLooper(), mBroadcastDispatcher,
                 mUserTracker);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
new file mode 100644
index 0000000..bf682a8
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2021 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.qs.tiles;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Intent;
+import android.os.Handler;
+import android.provider.Settings;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.FakeSettings;
+import com.android.systemui.util.settings.SecureSettings;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@SmallTest
+public class ColorInversionTileTest extends SysuiTestCase {
+
+    @Mock
+    private QSTileHost mHost;
+    @Mock
+    private MetricsLogger mMetricsLogger;
+    @Mock
+    private StatusBarStateController mStatusBarStateController;
+    @Mock
+    private ActivityStarter mActivityStarter;
+    @Mock
+    private QSLogger mQSLogger;
+    @Mock
+    private UiEventLogger mUiEventLogger;
+    @Mock
+    private UserTracker mUserTracker;
+
+    private TestableLooper mTestableLooper;
+    private SecureSettings mSecureSettings;
+    private ColorInversionTile mTile;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mSecureSettings = new FakeSettings();
+        mTestableLooper = TestableLooper.get(this);
+
+        when(mHost.getContext()).thenReturn(mContext);
+        when(mHost.getUiEventLogger()).thenReturn(mUiEventLogger);
+
+        mTile = new ColorInversionTile(
+                mHost,
+                mTestableLooper.getLooper(),
+                new Handler(mTestableLooper.getLooper()),
+                new FalsingManagerFake(),
+                mMetricsLogger,
+                mStatusBarStateController,
+                mActivityStarter,
+                mQSLogger,
+                mUserTracker,
+                mSecureSettings
+        );
+
+        mTile.initialize();
+        mTestableLooper.processAllMessages();
+    }
+
+    @Test
+    public void longClick_expectedAction() {
+        final ArgumentCaptor<Intent> IntentCaptor = ArgumentCaptor.forClass(Intent.class);
+
+        mTile.longClick(/* view= */ null);
+        mTestableLooper.processAllMessages();
+
+        verify(mActivityStarter).postStartActivityDismissingKeyguard(IntentCaptor.capture(),
+                anyInt(), any());
+        assertThat(IntentCaptor.getValue().getAction()).isEqualTo(
+                Settings.ACTION_COLOR_INVERSION_SETTINGS);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
new file mode 100644
index 0000000..3ea2cc5
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DndTileTest.kt
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2021 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.qs.tiles
+
+import android.app.Dialog
+import android.content.ContextWrapper
+import android.content.SharedPreferences
+import android.os.Handler
+import android.provider.Settings
+import android.provider.Settings.Global.ZEN_MODE_OFF
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.DialogLaunchAnimator
+import com.android.systemui.classifier.FalsingManagerFake
+import com.android.systemui.plugins.ActivityStarter
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.qs.QSHost
+import com.android.systemui.qs.logging.QSLogger
+import com.android.systemui.statusbar.policy.ZenModeController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.settings.FakeSettings
+import com.android.systemui.util.settings.SecureSettings
+import com.google.common.truth.Truth.assertThat
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.anyBoolean
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+import java.io.File
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class DndTileTest : SysuiTestCase() {
+
+    companion object {
+        private const val DEFAULT_USER = 0
+        private const val KEY = Settings.Secure.ZEN_DURATION
+    }
+
+    @Mock
+    private lateinit var qsHost: QSHost
+    @Mock
+    private lateinit var metricsLogger: MetricsLogger
+    @Mock
+    private lateinit var statusBarStateController: StatusBarStateController
+    @Mock
+    private lateinit var activityStarter: ActivityStarter
+    @Mock
+    private lateinit var qsLogger: QSLogger
+    @Mock
+    private lateinit var uiEventLogger: UiEventLogger
+    @Mock
+    private lateinit var zenModeController: ZenModeController
+    @Mock
+    private lateinit var sharedPreferences: SharedPreferences
+    @Mock
+    private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
+    @Mock
+    private lateinit var hostDialog: Dialog
+
+    private lateinit var secureSettings: SecureSettings
+    private lateinit var testableLooper: TestableLooper
+    private lateinit var tile: DndTile
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        testableLooper = TestableLooper.get(this)
+        secureSettings = FakeSettings()
+
+        whenever(qsHost.userId).thenReturn(DEFAULT_USER)
+        whenever(qsHost.uiEventLogger).thenReturn(uiEventLogger)
+        whenever(dialogLaunchAnimator.showFromView(any(), any(), anyBoolean()))
+                .thenReturn(hostDialog)
+
+        val wrappedContext = object : ContextWrapper(context) {
+            override fun getSharedPreferences(file: File?, mode: Int): SharedPreferences {
+                return sharedPreferences
+            }
+        }
+        whenever(qsHost.context).thenReturn(wrappedContext)
+
+        tile = DndTile(
+            qsHost,
+            testableLooper.looper,
+            Handler(testableLooper.looper),
+            FalsingManagerFake(),
+            metricsLogger,
+            statusBarStateController,
+            activityStarter,
+            qsLogger,
+            zenModeController,
+            sharedPreferences,
+            secureSettings,
+            dialogLaunchAnimator
+        )
+    }
+
+    @After
+    fun tearDown() {
+        tile.handleSetListening(false)
+    }
+
+    @Test
+    fun testForceExpandIcon_durationAskAlways_true() {
+        secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER)
+
+        tile.refreshState()
+        testableLooper.processAllMessages()
+
+        assertThat(tile.state.forceExpandIcon).isTrue()
+    }
+
+    @Test
+    fun testForceExpandIcon_durationNotAskAlways_false() {
+        secureSettings.putIntForUser(KEY, 60, DEFAULT_USER)
+
+        tile.refreshState()
+        testableLooper.processAllMessages()
+
+        assertThat(tile.state.forceExpandIcon).isFalse()
+    }
+
+    @Test
+    fun testForceExpandIcon_changeWhileListening() {
+        secureSettings.putIntForUser(KEY, 60, DEFAULT_USER)
+
+        tile.refreshState()
+        testableLooper.processAllMessages()
+
+        assertThat(tile.state.forceExpandIcon).isFalse()
+
+        tile.handleSetListening(true)
+
+        secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER)
+        testableLooper.processAllMessages()
+
+        assertThat(tile.state.forceExpandIcon).isTrue()
+    }
+
+    @Test
+    fun testLaunchDialogFromViewWhenPrompt() {
+        whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
+
+        secureSettings.putIntForUser(KEY, Settings.Secure.ZEN_DURATION_PROMPT, DEFAULT_USER)
+        testableLooper.processAllMessages()
+
+        val view = View(context)
+        tile.handleClick(view)
+        testableLooper.processAllMessages()
+
+        verify(dialogLaunchAnimator).showFromView(any(), eq(view), anyBoolean())
+    }
+
+    @Test
+    fun testNoLaunchDialogWhenNotPrompt() {
+        whenever(zenModeController.zen).thenReturn(ZEN_MODE_OFF)
+
+        secureSettings.putIntForUser(KEY, 60, DEFAULT_USER)
+        testableLooper.processAllMessages()
+
+        val view = View(context)
+        tile.handleClick(view)
+        testableLooper.processAllMessages()
+
+        verify(dialogLaunchAnimator, never()).showFromView(any(), any(), anyBoolean())
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
new file mode 100644
index 0000000..8031875
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/OneHandedModeTileTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2021 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.qs.tiles;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.os.Handler;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.settings.UserTracker;
+import com.android.systemui.util.settings.SecureSettings;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@SmallTest
+public class OneHandedModeTileTest extends SysuiTestCase {
+
+    private final String mOneHandedTitle = "One-handed mode";
+
+    @Mock
+    private ActivityStarter mActivityStarter;
+    @Mock
+    private QSTileHost mHost;
+    @Mock
+    private MetricsLogger mMetricsLogger;
+    @Mock
+    private StatusBarStateController mStatusBarStateController;
+    @Mock
+    private QSLogger mQSLogger;
+    @Mock
+    private UserTracker mUserTracker;
+    @Mock
+    private SecureSettings mSecureSettings;
+
+    private TestableLooper mTestableLooper;
+    private OneHandedModeTile mTile;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mTestableLooper = TestableLooper.get(this);
+
+        when(mHost.getContext()).thenReturn(mContext);
+
+        mTile = spy(new OneHandedModeTile(
+                mHost,
+                mTestableLooper.getLooper(),
+                new Handler(mTestableLooper.getLooper()),
+                new FalsingManagerFake(),
+                mMetricsLogger,
+                mStatusBarStateController,
+                mActivityStarter,
+                mQSLogger,
+                mUserTracker,
+                mSecureSettings));
+
+        mTestableLooper.processAllMessages();
+        mTile.initialize();
+    }
+
+    @Test
+    public void testIsAvailable_unsupportOneHandedProperty_shouldReturnsFalse() {
+        when(mTile.isSupportOneHandedMode()).thenReturn(false);
+
+        assertThat(mTile.isAvailable()).isFalse();
+    }
+
+    @Test
+    public void testIsAvailable_supportOneHandedProperty_shouldReturnsTrue() {
+        when(mTile.isSupportOneHandedMode()).thenReturn(true);
+
+        assertThat(mTile.isAvailable()).isTrue();
+    }
+
+    @Test
+    public void testGetTileLabel_shouldReturnOneHandedModeTitle() {
+        assertThat(mTile.getTileLabel()).isEqualTo(mOneHandedTitle);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index b6e8979..339d5bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -1,5 +1,7 @@
 package com.android.systemui.qs.tiles.dialog;
 
+import static com.android.systemui.qs.tiles.dialog.InternetDialogController.MAX_WIFI_ENTRY_COUNT;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
@@ -219,61 +221,91 @@
     }
 
     @Test
-    public void updateDialog_wifiOnAndNoWifiList_hideWifiListAndSeeAll() {
+    public void updateDialog_wifiOnAndNoWifiEntry_showWifiListAndSeeAllArea() {
         // The precondition WiFi ON is already in setUp()
+        mInternetDialog.mConnectedWifiEntry = null;
         mInternetDialog.mWifiEntriesCount = 0;
 
         mInternetDialog.updateDialog(false);
 
-        assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+        // Show a blank block to fix the dialog height even if there is no WiFi list
+        assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mSeeAll.getVisibility()).isEqualTo(View.INVISIBLE);
     }
 
     @Test
-    public void updateDialog_wifiOnAndHasWifiList_showWifiListAndSeeAll() {
+    public void updateDialog_wifiOnAndHasConnectedWifi_showAllWifiAndSeeAllArea() {
         // The preconditions WiFi ON and WiFi entries are already in setUp()
+        mInternetDialog.mWifiEntriesCount = 0;
 
         mInternetDialog.updateDialog(false);
 
+        assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
+        // Show a blank block to fix the dialog height even if there is no WiFi list
         assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
     }
 
     @Test
-    public void updateDialog_deviceLockedAndHasInternetWifi_showHighlightWifiToggle() {
-        // The preconditions WiFi ON and Internet WiFi are already in setUp()
-        when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
-
-        mInternetDialog.updateDialog(false);
-
-        assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(mWifiToggle.getBackground()).isNotNull();
-    }
-
-    @Test
-    public void updateDialog_deviceLockedAndHasInternetWifi_hideConnectedWifi() {
-        // The preconditions WiFi ON and Internet WiFi are already in setUp()
-        when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+    public void updateDialog_wifiOnAndHasWifiList_showWifiListAndSeeAll() {
+        // The preconditions WiFi ON and WiFi entries are already in setUp()
+        mInternetDialog.mConnectedWifiEntry = null;
 
         mInternetDialog.updateDialog(false);
 
         assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
     }
 
     @Test
-    public void updateDialog_deviceLockedAndHasWifiList_hideWifiListAndSeeAll() {
+    public void updateDialog_wifiOnAndHasBothWifiEntry_showBothWifiEntryAndSeeAll() {
+        // The preconditions WiFi ON and WiFi entries are already in setUp()
+
+        mInternetDialog.updateDialog(false);
+
+        assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+
+    @Test
+    public void updateDialog_deviceLockedAndNoConnectedWifi_showWifiToggle() {
         // The preconditions WiFi entries are already in setUp()
         when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+        mInternetDialog.mConnectedWifiEntry = null;
+
+        mInternetDialog.updateDialog(false);
+
+        // Show WiFi Toggle without background
+        assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mWifiToggle.getBackground()).isNull();
+        // Hide Wi-Fi networks and See all
+        assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void updateDialog_deviceLockedAndHasConnectedWifi_showWifiToggleWithBackground() {
+        // The preconditions WiFi ON and WiFi entries are already in setUp()
+        when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
 
         mInternetDialog.updateDialog(false);
 
+        // Show WiFi Toggle with highlight background
+        assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mWifiToggle.getBackground()).isNotNull();
+        // Hide Wi-Fi networks and See all
+        assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
         assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
         assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
     public void updateDialog_wifiOn_hideWifiScanNotify() {
-        // The preconditions WiFi ON and Internet WiFi are already in setUp()
+        // The preconditions WiFi ON and WiFi entries are already in setUp()
 
         mInternetDialog.updateDialog(false);
 
@@ -384,4 +416,54 @@
         assertThat(mInternetDialog.mIsProgressBarVisible).isTrue();
         assertThat(mInternetDialog.mIsSearchingHidden).isTrue();
     }
+
+    @Test
+    public void getWifiListMaxCount_returnCountCorrectly() {
+        // Ethernet, MobileData, ConnectedWiFi are all hidden.
+        // Then the maximum count is equal to MAX_WIFI_ENTRY_COUNT.
+        setNetworkVisible(false, false, false);
+
+        assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT);
+
+        // Only one of Ethernet, MobileData, ConnectedWiFi is displayed.
+        // Then the maximum count  is equal to MAX_WIFI_ENTRY_COUNT - 1.
+        setNetworkVisible(true, false, false);
+
+        assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 1);
+
+        setNetworkVisible(false, true, false);
+
+        assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 1);
+
+        setNetworkVisible(false, false, true);
+
+        assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 1);
+
+        // Only one of Ethernet, MobileData, ConnectedWiFi is hidden.
+        // Then the maximum count  is equal to MAX_WIFI_ENTRY_COUNT - 2.
+        setNetworkVisible(true, true, false);
+
+        assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 2);
+
+        setNetworkVisible(true, false, true);
+
+        assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 2);
+
+        setNetworkVisible(false, true, true);
+
+        assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 2);
+
+        // Ethernet, MobileData, ConnectedWiFi are all displayed.
+        // Then the maximum count  is equal to MAX_WIFI_ENTRY_COUNT - 3.
+        setNetworkVisible(true, true, true);
+
+        assertThat(mInternetDialog.getWifiListMaxCount()).isEqualTo(MAX_WIFI_ENTRY_COUNT - 3);
+    }
+
+    private void setNetworkVisible(boolean ethernetVisible, boolean mobileDataVisible,
+            boolean connectedWifiVisible) {
+        mEthernet.setVisibility(ethernetVisible ? View.VISIBLE : View.GONE);
+        mMobileDataToggle.setVisibility(mobileDataVisible ? View.VISIBLE : View.GONE);
+        mConnectedWifi.setVisibility(connectedWifiVisible ? View.VISIBLE : View.GONE);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserDialogTest.kt
deleted file mode 100644
index d5fe588..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserDialogTest.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2021 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.qs.user
-
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import android.view.View
-import android.view.ViewGroup
-import androidx.test.filters.SmallTest
-import com.android.systemui.SysuiTestCase
-import com.google.common.truth.Truth.assertThat
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@SmallTest
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper
-class UserDialogTest : SysuiTestCase() {
-
-    private lateinit var dialog: UserDialog
-
-    @Before
-    fun setUp() {
-        dialog = UserDialog(mContext)
-    }
-
-    @After
-    fun tearDown() {
-        dialog.dismiss()
-    }
-
-    @Test
-    fun doneButtonExists() {
-        assertThat(dialog.doneButton).isInstanceOf(View::class.java)
-    }
-
-    @Test
-    fun settingsButtonExists() {
-        assertThat(dialog.settingsButton).isInstanceOf(View::class.java)
-    }
-
-    @Test
-    fun gridExistsAndIsViewGroup() {
-        assertThat(dialog.grid).isInstanceOf(ViewGroup::class.java)
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
index 7e900c8..3c4a557 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/user/UserSwitchDialogControllerTest.kt
@@ -16,6 +16,8 @@
 
 package com.android.systemui.qs.user
 
+import android.app.Dialog
+import android.content.DialogInterface
 import android.content.Intent
 import android.provider.Settings
 import android.testing.AndroidTestingRunner
@@ -27,7 +29,8 @@
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.qs.PseudoGridView
 import com.android.systemui.qs.tiles.UserDetailView
-import com.android.systemui.statusbar.policy.UserSwitcherController
+import com.android.systemui.statusbar.phone.SystemUIDialog
+import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.argumentCaptor
 import com.android.systemui.util.mockito.capture
 import com.android.systemui.util.mockito.eq
@@ -39,40 +42,33 @@
 import org.mockito.Captor
 import org.mockito.Mock
 import org.mockito.Mockito.`when`
-import org.mockito.Mockito.any
+import org.mockito.Mockito.anyBoolean
 import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.argThat
-import org.mockito.Mockito.inOrder
-import org.mockito.Mockito.mock
 import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
-import java.util.function.Consumer
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
 class UserSwitchDialogControllerTest : SysuiTestCase() {
 
     @Mock
-    private lateinit var dialog: UserDialog
+    private lateinit var dialog: SystemUIDialog
     @Mock
     private lateinit var falsingManager: FalsingManager
     @Mock
-    private lateinit var settingsView: View
-    @Mock
-    private lateinit var doneView: View
-    @Mock
     private lateinit var activityStarter: ActivityStarter
     @Mock
     private lateinit var userDetailViewAdapter: UserDetailView.Adapter
     @Mock
     private lateinit var launchView: View
     @Mock
-    private lateinit var gridView: PseudoGridView
-    @Mock
     private lateinit var dialogLaunchAnimator: DialogLaunchAnimator
+    @Mock
+    private lateinit var hostDialog: Dialog
     @Captor
-    private lateinit var clickCaptor: ArgumentCaptor<View.OnClickListener>
+    private lateinit var clickCaptor: ArgumentCaptor<DialogInterface.OnClickListener>
 
     private lateinit var controller: UserSwitchDialogController
 
@@ -80,11 +76,10 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        `when`(dialog.settingsButton).thenReturn(settingsView)
-        `when`(dialog.doneButton).thenReturn(doneView)
-        `when`(dialog.grid).thenReturn(gridView)
-
         `when`(launchView.context).thenReturn(mContext)
+        `when`(dialog.context).thenReturn(mContext)
+        `when`(dialogLaunchAnimator.showFromView(any(), any(), anyBoolean()))
+                .thenReturn(hostDialog)
 
         controller = UserSwitchDialogController(
                 { userDetailViewAdapter },
@@ -102,30 +97,6 @@
     }
 
     @Test
-    fun createCalledBeforeDoneButton() {
-        controller.showDialog(launchView)
-        val inOrder = inOrder(dialog)
-        inOrder.verify(dialog).create()
-        inOrder.verify(dialog).doneButton
-    }
-
-    @Test
-    fun createCalledBeforeSettingsButton() {
-        controller.showDialog(launchView)
-        val inOrder = inOrder(dialog)
-        inOrder.verify(dialog).create()
-        inOrder.verify(dialog).settingsButton
-    }
-
-    @Test
-    fun createCalledBeforeGrid() {
-        controller.showDialog(launchView)
-        val inOrder = inOrder(dialog)
-        inOrder.verify(dialog).create()
-        inOrder.verify(dialog).grid
-    }
-
-    @Test
     fun dialog_showForAllUsers() {
         controller.showDialog(launchView)
         verify(dialog).setShowForAllUsers(true)
@@ -140,63 +111,56 @@
     @Test
     fun adapterAndGridLinked() {
         controller.showDialog(launchView)
-        verify(userDetailViewAdapter).linkToViewGroup(gridView)
+        verify(userDetailViewAdapter).linkToViewGroup(any<PseudoGridView>())
     }
 
     @Test
-    fun clickDoneButton_dismiss() {
+    fun doneButtonSetWithNullHandler() {
         controller.showDialog(launchView)
 
-        verify(doneView).setOnClickListener(capture(clickCaptor))
-
-        clickCaptor.value.onClick(doneView)
-
-        verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt())
-        verify(dialog).dismiss()
+        verify(dialog).setPositiveButton(anyInt(), eq(null))
     }
 
     @Test
-    fun clickSettingsButton_noFalsing_opensSettingsAndDismisses() {
+    fun clickSettingsButton_noFalsing_opensSettings() {
         `when`(falsingManager.isFalseTap(anyInt())).thenReturn(false)
 
         controller.showDialog(launchView)
 
-        verify(settingsView).setOnClickListener(capture(clickCaptor))
+        verify(dialog).setNeutralButton(anyInt(), capture(clickCaptor))
 
-        clickCaptor.value.onClick(settingsView)
+        clickCaptor.value.onClick(dialog, DialogInterface.BUTTON_NEUTRAL)
 
         verify(activityStarter)
                 .postStartActivityDismissingKeyguard(
                         argThat(IntentMatcher(Settings.ACTION_USER_SETTINGS)),
                         eq(0)
                 )
-        verify(dialog).dismiss()
     }
 
     @Test
-    fun clickSettingsButton_Falsing_notOpensSettingsAndDismisses() {
+    fun clickSettingsButton_Falsing_notOpensSettings() {
         `when`(falsingManager.isFalseTap(anyInt())).thenReturn(true)
 
         controller.showDialog(launchView)
 
-        verify(settingsView).setOnClickListener(capture(clickCaptor))
+        verify(dialog).setNeutralButton(anyInt(), capture(clickCaptor))
 
-        clickCaptor.value.onClick(settingsView)
+        clickCaptor.value.onClick(dialog, DialogInterface.BUTTON_NEUTRAL)
 
         verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt())
-        verify(dialog).dismiss()
     }
 
     @Test
-    fun callbackFromDetailView_dismissesDialog() {
-        val captor = argumentCaptor<Consumer<UserSwitcherController.UserRecord>>()
+    fun callbackFromDialogShower_dismissesDialog() {
+        val captor = argumentCaptor<UserSwitchDialogController.DialogShower>()
 
         controller.showDialog(launchView)
-        verify(userDetailViewAdapter).injectCallback(capture(captor))
+        verify(userDetailViewAdapter).injectDialogShower(capture(captor))
 
-        captor.value.accept(mock(UserSwitcherController.UserRecord::class.java))
+        captor.value.dismiss()
 
-        verify(dialog).dismiss()
+        verify(hostDialog).dismiss()
     }
 
     private class IntentMatcher(private val action: String) : ArgumentMatcher<Intent> {
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 b0f2a89..4213b07 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -29,6 +29,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener;
@@ -54,6 +55,7 @@
 @TestableLooper.RunWithLooper(setAsMainLooper = true)
 public class NonPhoneDependencyTest extends SysuiTestCase {
     @Mock private NotificationPresenter mPresenter;
+    @Mock private NotifStackController mStackController;
     @Mock private NotificationListContainer mListContainer;
     @Mock
     private NotificationEntryListener mEntryListener;
@@ -95,7 +97,7 @@
         remoteInputManager.setUpWithCallback(mRemoteInputManagerCallback,
                 mDelegate);
         lockscreenUserManager.setUpWithPresenter(mPresenter);
-        viewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
+        viewHierarchyManager.setUpWithPresenter(mPresenter, mStackController, mListContainer);
 
         TestableLooper.get(this).processAllMessages();
         assertFalse(mDependency.hasInstantiatedDependency(NotificationShadeWindowController.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
index 8e4b98f..bd9f91f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationRemoteInputManagerTest.java
@@ -39,11 +39,11 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationRemoteInputManager.LegacyRemoteInputLifetimeExtender.RemoteInputActiveExtender;
 import com.android.systemui.statusbar.NotificationRemoteInputManager.LegacyRemoteInputLifetimeExtender.RemoteInputHistoryExtender;
 import com.android.systemui.statusbar.NotificationRemoteInputManager.LegacyRemoteInputLifetimeExtender.SmartReplyHistoryExtender;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -99,7 +99,7 @@
         MockitoAnnotations.initMocks(this);
 
         mRemoteInputManager = new TestableNotificationRemoteInputManager(mContext,
-                mock(FeatureFlags.class),
+                mock(NotifPipelineFlags.class),
                 mLockscreenUserManager,
                 mSmartReplyController,
                 mVisibilityProvider,
@@ -190,7 +190,7 @@
 
         TestableNotificationRemoteInputManager(
                 Context context,
-                FeatureFlags featureFlags,
+                NotifPipelineFlags notifPipelineFlags,
                 NotificationLockscreenUserManager lockscreenUserManager,
                 SmartReplyController smartReplyController,
                 NotificationVisibilityProvider visibilityProvider,
@@ -205,7 +205,7 @@
                 DumpManager dumpManager) {
             super(
                     context,
-                    featureFlags,
+                    notifPipelineFlags,
                     lockscreenUserManager,
                     smartReplyController,
                     visibilityProvider,
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 9a23eb6..83f1d87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -41,12 +41,14 @@
 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.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.legacy.LowPriorityInflationHelper;
 import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
 import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
@@ -73,10 +75,12 @@
 @TestableLooper.RunWithLooper
 public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
     @Mock private NotificationPresenter mPresenter;
+    @Mock private NotifStackController mStackController;
     @Spy private FakeListContainer mListContainer = new FakeListContainer();
 
     // Dependency mocks:
     @Mock private FeatureFlags mFeatureFlags;
+    @Mock private NotifPipelineFlags mNotifPipelineFlags;
     @Mock private NotificationEntryManager mEntryManager;
     @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
     @Mock private NotificationGroupManagerLegacy mGroupManager;
@@ -103,7 +107,8 @@
         when(mVisualStabilityManager.areGroupChangesAllowed()).thenReturn(true);
         when(mVisualStabilityManager.isReorderingAllowed()).thenReturn(true);
 
-        when(mFeatureFlags.checkLegacyPipelineEnabled()).thenReturn(true);
+        when(mNotifPipelineFlags.checkLegacyPipelineEnabled()).thenReturn(true);
+        when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
 
         mHelper = new NotificationTestHelper(mContext, mDependency, TestableLooper.get(this));
 
@@ -117,8 +122,9 @@
                 mock(ForegroundServiceSectionController.class),
                 mock(DynamicChildBindController.class),
                 mock(LowPriorityInflationHelper.class),
-                mock(AssistantFeedbackController.class));
-        mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer);
+                mock(AssistantFeedbackController.class),
+                mNotifPipelineFlags);
+        mViewHierarchyManager.setUpWithPresenter(mPresenter, mStackController, mListContainer);
     }
 
     private NotificationEntry createEntry() throws Exception {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
index 8b28fd5..e0689f3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SmartReplyControllerTest.java
@@ -39,8 +39,8 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -97,7 +97,7 @@
                 mSmartReplyController);
 
         mRemoteInputManager = new NotificationRemoteInputManager(mContext,
-                mock(FeatureFlags.class),
+                mock(NotifPipelineFlags.class),
                 mock(NotificationLockscreenUserManager.class),
                 mSmartReplyController,
                 mVisibilityProvider,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/charging/WiredChargingRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/charging/WiredChargingRippleControllerTest.kt
index f2671b76..ecc2a1b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/charging/WiredChargingRippleControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/charging/WiredChargingRippleControllerTest.kt
@@ -23,6 +23,7 @@
 import com.android.internal.logging.UiEventLogger
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.statusbar.commandline.CommandRegistry
 import com.android.systemui.statusbar.policy.BatteryController
 import com.android.systemui.statusbar.policy.ConfigurationController
@@ -57,7 +58,7 @@
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
-        `when`(featureFlags.isChargingRippleEnabled).thenReturn(true)
+        `when`(featureFlags.isEnabled(Flags.CHARGING_RIPPLE)).thenReturn(true)
         controller = WiredChargingRippleController(
                 commandRegistry, batteryController, configurationController,
                 featureFlags, context, windowManager, systemClock, uiEventLogger)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
index 47a11fc..ee6324b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
@@ -60,7 +60,6 @@
 
 import androidx.test.InstrumentationRegistry;
 
-import com.android.dx.mockito.inline.extended.ExtendedMockito;
 import com.android.settingslib.R;
 import com.android.settingslib.graph.SignalDrawable;
 import com.android.settingslib.mobile.MobileMappings.Config;
@@ -72,6 +71,7 @@
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 import com.android.systemui.telephony.TelephonyListenerManager;
@@ -87,7 +87,6 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mockito;
 import org.mockito.MockitoSession;
-import org.mockito.quality.Strictness;
 
 import java.io.PrintWriter;
 import java.io.StringWriter;
@@ -127,6 +126,7 @@
     protected CarrierConfigTracker mCarrierConfigTracker;
     protected FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
     protected FeatureFlags mFeatureFlags;
+    protected StatusBarFlags mStatusBarFlags;
 
     protected int mSubId;
 
@@ -156,13 +156,10 @@
 
     @Before
     public void setUp() throws Exception {
-        mMockingSession = ExtendedMockito.mockitoSession().strictness(Strictness.LENIENT)
-                .mockStatic(FeatureFlags.class).startMocking();
-        ExtendedMockito.doReturn(true).when(() ->
-                FeatureFlags.isProviderModelSettingEnabled(mContext));
         mFeatureFlags = mock(FeatureFlags.class);
-        when(mFeatureFlags.isCombinedStatusBarSignalIconsEnabled()).thenReturn(false);
-        when(mFeatureFlags.isProviderModelSettingEnabled()).thenReturn(true);
+        mStatusBarFlags = mock(StatusBarFlags.class);
+        when(mFeatureFlags.isEnabled(Flags.COMBINED_STATUS_BAR_SIGNAL_ICONS)).thenReturn(false);
+        when(mStatusBarFlags.isProviderModelSettingEnabled()).thenReturn(true);
 
 
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
@@ -241,6 +238,7 @@
                 mDemoModeController,
                 mCarrierConfigTracker,
                 mFeatureFlags,
+                mStatusBarFlags,
                 mock(DumpManager.class)
         );
         setupNetworkController();
@@ -310,7 +308,7 @@
                         mock(AccessPointControllerImpl.class),
                         mock(DataUsageController.class), mMockSubDefaults,
                         mock(DeviceProvisionedController.class), mMockBd, mDemoModeController,
-                        mCarrierConfigTracker, mFeatureFlags,
+                        mCarrierConfigTracker, mFeatureFlags, mStatusBarFlags,
                         mock(DumpManager.class));
 
         setupNetworkController();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
index 12f8282..0ed4243 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
@@ -130,7 +130,8 @@
                 mock(AccessPointControllerImpl.class),
                 mock(DataUsageController.class), mMockSubDefaults,
                 mock(DeviceProvisionedController.class), mMockBd, mDemoModeController,
-                mock(CarrierConfigTracker.class), mFeatureFlags, mock(DumpManager.class));
+                mock(CarrierConfigTracker.class), mFeatureFlags, mStatusBarFlags,
+                mock(DumpManager.class));
         setupNetworkController();
 
         setupDefaultSignal();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
index 73eddd1..64da141 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerSignalTest.java
@@ -70,7 +70,7 @@
                 mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
                 mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
                 mDemoModeController, mock(CarrierConfigTracker.class), mFeatureFlags,
-                mock(DumpManager.class));
+                mStatusBarFlags, mock(DumpManager.class));
         setupNetworkController();
 
         verifyLastMobileDataIndicators(false, -1, 0);
@@ -91,7 +91,7 @@
                 mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
                 mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
                 mDemoModeController, mock(CarrierConfigTracker.class), mFeatureFlags,
-                mock(DumpManager.class));
+                mStatusBarFlags, mock(DumpManager.class));
         mNetworkController.registerListeners();
 
         // Wait for the main looper to execute the previous command
@@ -160,7 +160,7 @@
                 mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
                 mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd,
                 mDemoModeController, mock(CarrierConfigTracker.class), mFeatureFlags,
-                mock(DumpManager.class));
+                mStatusBarFlags, mock(DumpManager.class));
         setupNetworkController();
 
         // No Subscriptions.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index ff91978..de627de 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -42,6 +42,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener
 import com.android.systemui.settings.UserTracker
 import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.statusbar.policy.ConfigurationController
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener
 import com.android.systemui.statusbar.policy.DeviceProvisionedController
@@ -144,7 +145,7 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        `when`(featureFlags.isSmartspaceEnabled).thenReturn(true)
+        `when`(featureFlags.isEnabled(Flags.SMARTSPACE)).thenReturn(true)
 
         `when`(secureSettings.getUriFor(PRIVATE_LOCKSCREEN_SETTING))
                 .thenReturn(fakePrivateLockscreenSettingUri)
@@ -185,7 +186,7 @@
     @Test(expected = RuntimeException::class)
     fun testThrowsIfFlagIsDisabled() {
         // GIVEN the feature flag is disabled
-        `when`(featureFlags.isSmartspaceEnabled).thenReturn(false)
+        `when`(featureFlags.isEnabled(Flags.SMARTSPACE)).thenReturn(false)
 
         // WHEN we try to build the view
         controller.buildAndConnectView(fakeParent)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index f8effa1..f62de51 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -66,7 +66,6 @@
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationMediaManager;
@@ -132,7 +131,7 @@
     @Mock private DeviceProvisionedController mDeviceProvisionedController;
     @Mock private RowInflaterTask mAsyncInflationTask;
     @Mock private NotificationEntryManagerLogger mLogger;
-    @Mock private FeatureFlags mFeatureFlags;
+    @Mock private NotifPipelineFlags mNotifPipelineFlags;
     @Mock private LeakDetector mLeakDetector;
     @Mock private NotificationMediaManager mNotificationMediaManager;
     @Mock private NotificationRowBinder mNotificationRowBinder;
@@ -192,11 +191,11 @@
         mEntry = createNotification();
         mSbn = mEntry.getSbn();
 
-        when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
+        when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
         mEntryManager = new NotificationEntryManager(
                 mLogger,
                 mGroupManager,
-                mFeatureFlags,
+                mNotifPipelineFlags,
                 () -> mNotificationRowBinder,
                 () -> mRemoteInputManager,
                 mLeakDetector,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index cf90cef6..41163bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -70,8 +70,8 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.dump.LogBufferEulogizer;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.collection.NoManSimulator.NotifEvent;
 import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
 import com.android.systemui.statusbar.notification.collection.coalescer.CoalescedEvent;
@@ -107,7 +107,7 @@
 public class NotifCollectionTest extends SysuiTestCase {
 
     @Mock private IStatusBarService mStatusBarService;
-    @Mock private FeatureFlags mFeatureFlags;
+    @Mock private NotifPipelineFlags mNotifPipelineFlags;
     @Mock private NotifCollectionLogger mLogger;
     @Mock private LogBufferEulogizer mEulogizer;
     @Mock private Handler mMainHandler;
@@ -144,7 +144,7 @@
         MockitoAnnotations.initMocks(this);
         allowTestableLooperAsMainThread();
 
-        when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(true);
+        when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(true);
 
         when(mEulogizer.record(any(Exception.class))).thenAnswer(i -> i.getArguments()[0]);
 
@@ -153,7 +153,7 @@
         mCollection = new NotifCollection(
                 mStatusBarService,
                 mClock,
-                mFeatureFlags,
+                mNotifPipelineFlags,
                 mLogger,
                 mMainHandler,
                 mEulogizer,
@@ -174,6 +174,41 @@
     }
 
     @Test
+    public void testGetGroupSummary() {
+        assertEquals(null, mCollection.getGroupSummary("group"));
+        NotifEvent summary = mNoMan.postNotif(
+                buildNotif(TEST_PACKAGE, 0)
+                        .setGroup(mContext, "group")
+                        .setGroupSummary(mContext, true));
+
+        final NotificationEntry entry = mCollection.getGroupSummary("group");
+        assertEquals(summary.key, entry.getKey());
+        assertEquals(summary.sbn, entry.getSbn());
+        assertEquals(summary.ranking, entry.getRanking());
+    }
+
+    @Test
+    public void testIsOnlyChildInGroup() {
+        NotifEvent notif1 = mNoMan.postNotif(
+                buildNotif(TEST_PACKAGE, 1)
+                        .setGroup(mContext, "group"));
+        final NotificationEntry entry = mCollection.getEntry(notif1.key);
+        assertTrue(mCollection.isOnlyChildInGroup(entry));
+
+        // summaries are not counted
+        mNoMan.postNotif(
+                buildNotif(TEST_PACKAGE, 0)
+                        .setGroup(mContext, "group")
+                        .setGroupSummary(mContext, true));
+        assertTrue(mCollection.isOnlyChildInGroup(entry));
+
+        mNoMan.postNotif(
+                buildNotif(TEST_PACKAGE, 2)
+                        .setGroup(mContext, "group"));
+        assertFalse(mCollection.isOnlyChildInGroup(entry));
+    }
+
+    @Test
     public void testEventDispatchedWhenNotifPosted() {
         // WHEN a notification is posted
         NotifEvent notif1 = mNoMan.postNotif(
@@ -193,6 +228,15 @@
     }
 
     @Test
+    public void testCancelNonExistingNotification() {
+        NotifEvent notif = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88, "barTag"));
+        NotificationEntry entry = mCollectionListener.getEntry(notif.key);
+        mCollection.dismissNotification(entry, defaultStats(entry));
+        mCollection.dismissNotification(entry, defaultStats(entry));
+        mCollection.dismissNotification(entry, defaultStats(entry));
+    }
+
+    @Test
     public void testEventDispatchedWhenNotifBatchPosted() {
         // GIVEN a NotifCollection with one notif already posted
         mNoMan.postNotif(buildNotif(TEST_PACKAGE, 2)
@@ -649,21 +693,6 @@
         // THEN an exception is thrown
     }
 
-    @Test(expected = IllegalStateException.class)
-    public void testDismissingNonExistentNotificationThrows() {
-        // GIVEN a collection that originally had three notifs, but where one was dismissed
-        NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 47));
-        NotifEvent notif2 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 88));
-        NotifEvent notif3 = mNoMan.postNotif(buildNotif(TEST_PACKAGE2, 99));
-        NotificationEntry entry2 = mCollectionListener.getEntry(notif2.key);
-        mNoMan.retractNotif(notif2.sbn, REASON_UNKNOWN);
-
-        // WHEN we try to dismiss a notification that isn't present
-        mCollection.dismissNotification(entry2, defaultStats(entry2));
-
-        // THEN an exception is thrown
-    }
-
     @Test
     public void testGroupChildrenAreDismissedLocallyWhenSummaryIsDismissed() {
         // GIVEN a collection with two grouped notifs in it
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineTest.kt
index cf7174e..287f50c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifPipelineTest.kt
@@ -19,6 +19,7 @@
 import android.testing.AndroidTestingRunner
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.render.RenderStageManager
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
@@ -33,12 +34,13 @@
 
     @Mock private lateinit var notifCollection: NotifCollection
     @Mock private lateinit var shadeListBuilder: ShadeListBuilder
+    @Mock private lateinit var renderStageManager: RenderStageManager
     private lateinit var notifPipeline: NotifPipeline
 
     @Before
     fun setup() {
         MockitoAnnotations.initMocks(this)
-        notifPipeline = NotifPipeline(notifCollection, shadeListBuilder)
+        notifPipeline = NotifPipeline(notifCollection, shadeListBuilder, renderStageManager)
         whenever(shadeListBuilder.shadeList).thenReturn(listOf(
                 NotificationEntryBuilder().setPkg("foo").setId(1).build(),
                 NotificationEntryBuilder().setPkg("foo").setId(2).build(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index b254ed4..82cd9fa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -32,7 +32,6 @@
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -52,6 +51,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.statusbar.NotificationInteractionTracker;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.collection.ShadeListBuilder.OnRenderListListener;
 import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection;
 import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener;
@@ -96,7 +96,9 @@
     private ShadeListBuilder mListBuilder;
     private FakeSystemClock mSystemClock = new FakeSystemClock();
 
+    @Mock private NotifPipelineFlags mNotifPipelineFlags;
     @Mock private ShadeListBuilderLogger mLogger;
+    @Mock private DumpManager mDumpManager;
     @Mock private NotifCollection mNotifCollection;
     @Mock private NotificationInteractionTracker mInteractionTracker;
     @Spy private OnBeforeTransformGroupsListener mOnBeforeTransformGroupsListener;
@@ -122,7 +124,12 @@
         allowTestableLooperAsMainThread();
 
         mListBuilder = new ShadeListBuilder(
-                mSystemClock, mLogger, mock(DumpManager.class), mInteractionTracker);
+                mSystemClock,
+                mNotifPipelineFlags,
+                mLogger,
+                mDumpManager,
+                mInteractionTracker
+        );
         mListBuilder.setOnRenderListListener(mOnRenderListListener);
 
         mListBuilder.attach(mNotifCollection);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinatorTest.java
index 01e4cce0..f4452bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/CommunalCoordinatorTest.java
@@ -17,6 +17,7 @@
 package com.android.systemui.statusbar.notification.collection.coordinator;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 
 import android.test.suitebuilder.annotation.SmallTest;
@@ -29,6 +30,8 @@
 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.Pluggable;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -39,6 +42,8 @@
 
 @SmallTest
 public class CommunalCoordinatorTest extends SysuiTestCase {
+    private final FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
+
     @Mock
     CommunalStateController mCommunalStateController;
     @Mock
@@ -57,7 +62,7 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        mCoordinator = new CommunalCoordinator(mNotificationEntryManager,
+        mCoordinator = new CommunalCoordinator(mExecutor, mNotificationEntryManager,
                 mNotificationLockscreenUserManager, mCommunalStateController);
     }
 
@@ -84,6 +89,12 @@
         // Verify that notifications are filtered out when communal is showing and that the filter
         // pipeline is notified.
         stateCallback.onCommunalViewShowingChanged();
+        // Make sure callback depends on executor to run.
+        verify(mFilterListener, never()).onPluggableInvalidated(any());
+        verify(mNotificationEntryManager, never()).updateNotifications(any());
+
+        mExecutor.runAllReady();
+
         verify(mFilterListener).onPluggableInvalidated(any());
         verify(mNotificationEntryManager).updateNotifications(any());
         assert (filter.shouldFilterOut(mNotificationEntry, 0));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinatorTest.kt
new file mode 100644
index 0000000..929c3d4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GroupCountCoordinatorTest.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2021 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 android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
+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.OnAfterRenderGroupListener
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener
+import com.android.systemui.statusbar.notification.collection.render.NotifGroupController
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.withArgCaptor
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations.initMocks
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class GroupCountCoordinatorTest : SysuiTestCase() {
+    private lateinit var coordinator: GroupCountCoordinator
+    private lateinit var beforeFinalizeFilterListener: OnBeforeFinalizeFilterListener
+    private lateinit var afterRenderGroupListener: OnAfterRenderGroupListener
+
+    private lateinit var summaryEntry: NotificationEntry
+    private lateinit var childEntry1: NotificationEntry
+    private lateinit var childEntry2: NotificationEntry
+
+    @Mock private lateinit var pipeline: NotifPipeline
+    @Mock private lateinit var groupController: NotifGroupController
+
+    @Before
+    fun setUp() {
+        initMocks(this)
+        coordinator = GroupCountCoordinator()
+        coordinator.attach(pipeline)
+        beforeFinalizeFilterListener = withArgCaptor {
+            verify(pipeline).addOnBeforeFinalizeFilterListener(capture())
+        }
+        afterRenderGroupListener = withArgCaptor {
+            verify(pipeline).addOnAfterRenderGroupListener(capture())
+        }
+        summaryEntry = NotificationEntryBuilder().setId(0).build()
+        childEntry1 = NotificationEntryBuilder().setId(1).build()
+        childEntry2 = NotificationEntryBuilder().setId(2).build()
+    }
+
+    @Test
+    fun testSetUntruncatedChildCount() {
+        val groupEntry = GroupEntryBuilder()
+            .setSummary(summaryEntry)
+            .setChildren(listOf(childEntry1, childEntry2))
+            .build()
+        beforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(groupEntry))
+        afterRenderGroupListener.onAfterRenderGroup(groupEntry, groupController)
+        verify(groupController).setUntruncatedChildCount(eq(2))
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
index c3e10aa..f70330d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java
@@ -40,6 +40,7 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.notification.SectionClassifier;
 import com.android.systemui.statusbar.notification.collection.GroupEntry;
 import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder;
 import com.android.systemui.statusbar.notification.collection.ListEntry;
@@ -85,7 +86,6 @@
 
     @Captor private ArgumentCaptor<NotifCollectionListener> mCollectionListenerCaptor;
     @Captor private ArgumentCaptor<OnBeforeFinalizeFilterListener> mBeforeFilterListenerCaptor;
-    @Captor private ArgumentCaptor<NotifInflater.InflationCallback> mCallbackCaptor;
     @Captor private ArgumentCaptor<NotifInflater.Params> mParamsCaptor;
 
     @Mock private NotifSectioner mNotifSectioner;
@@ -93,7 +93,9 @@
     @Mock private NotifPipeline mNotifPipeline;
     @Mock private IStatusBarService mService;
     @Spy private FakeNotifInflater mNotifInflater = new FakeNotifInflater();
-    private final TestableAdjustmentProvider mAdjustmentProvider = new TestableAdjustmentProvider();
+    private final SectionClassifier mSectionClassifier = new SectionClassifier();
+    private final NotifUiAdjustmentProvider mAdjustmentProvider =
+            new NotifUiAdjustmentProvider(mSectionClassifier);
 
     @NonNull
     private NotificationEntryBuilder getNotificationEntryBuilder() {
@@ -108,7 +110,7 @@
         mInflationError = new Exception(TEST_MESSAGE);
         mErrorManager = new NotifInflationErrorManager();
         when(mNotifSection.getSectioner()).thenReturn(mNotifSectioner);
-        mAdjustmentProvider.setSectionIsLowPriority(false);
+        setSectionIsLowPriority(false);
 
         PreparationCoordinator coordinator = new PreparationCoordinator(
                 mock(PreparationCoordinatorLogger.class),
@@ -180,8 +182,8 @@
         // GIVEN an inflated notification
         mCollectionListener.onEntryAdded(mEntry);
         mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry));
-        verify(mNotifInflater).inflateViews(eq(mEntry), any(), mCallbackCaptor.capture());
-        mCallbackCaptor.getValue().onInflationFinished(mEntry);
+        verify(mNotifInflater).inflateViews(eq(mEntry), any(), any());
+        mNotifInflater.invokeInflateCallbackForEntry(mEntry);
 
         // WHEN notification is updated
         mCollectionListener.onEntryUpdated(mEntry);
@@ -199,8 +201,8 @@
         // GIVEN an inflated notification
         mCollectionListener.onEntryAdded(mEntry);
         mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry));
-        verify(mNotifInflater).inflateViews(eq(mEntry), any(), mCallbackCaptor.capture());
-        mCallbackCaptor.getValue().onInflationFinished(mEntry);
+        verify(mNotifInflater).inflateViews(eq(mEntry), any(), any());
+        mNotifInflater.invokeInflateCallbackForEntry(mEntry);
 
         // WHEN notification ranking now has smart replies
         mEntry.setRanking(new RankingBuilder(mEntry.getRanking()).setSmartReplies("yes").build());
@@ -218,13 +220,12 @@
         // GIVEN an inflated notification
         mCollectionListener.onEntryAdded(mEntry);
         mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry));
-        verify(mNotifInflater).inflateViews(eq(mEntry),
-                mParamsCaptor.capture(), mCallbackCaptor.capture());
+        verify(mNotifInflater).inflateViews(eq(mEntry), mParamsCaptor.capture(), any());
         assertFalse(mParamsCaptor.getValue().isLowPriority());
-        mCallbackCaptor.getValue().onInflationFinished(mEntry);
+        mNotifInflater.invokeInflateCallbackForEntry(mEntry);
 
         // WHEN notification moves to a min priority section
-        mAdjustmentProvider.setSectionIsLowPriority(true);
+        setSectionIsLowPriority(true);
         mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry));
 
         // THEN we rebind it
@@ -238,13 +239,12 @@
     @Test
     public void testMinimizedEntryMovedIntoGroupWillRebindViews() {
         // GIVEN an inflated, minimized notification
-        mAdjustmentProvider.setSectionIsLowPriority(true);
+        setSectionIsLowPriority(true);
         mCollectionListener.onEntryAdded(mEntry);
         mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry));
-        verify(mNotifInflater).inflateViews(eq(mEntry),
-                mParamsCaptor.capture(), mCallbackCaptor.capture());
+        verify(mNotifInflater).inflateViews(eq(mEntry), mParamsCaptor.capture(), any());
         assertTrue(mParamsCaptor.getValue().isLowPriority());
-        mCallbackCaptor.getValue().onInflationFinished(mEntry);
+        mNotifInflater.invokeInflateCallbackForEntry(mEntry);
 
         // WHEN notification is moved under a parent
         NotificationEntryBuilder.setNewParent(mEntry, mock(GroupEntry.class));
@@ -263,8 +263,8 @@
         // GIVEN an inflated notification
         mCollectionListener.onEntryAdded(mEntry);
         mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry));
-        verify(mNotifInflater).inflateViews(eq(mEntry), any(), mCallbackCaptor.capture());
-        mCallbackCaptor.getValue().onInflationFinished(mEntry);
+        verify(mNotifInflater).inflateViews(eq(mEntry), any(), any());
+        mNotifInflater.invokeInflateCallbackForEntry(mEntry);
 
         // WHEN notification ranking changes rank, which does not affect views
         mEntry.setRanking(new RankingBuilder(mEntry.getRanking()).setRank(100).build());
@@ -282,8 +282,8 @@
         // GIVEN an inflated notification
         mCollectionListener.onEntryAdded(mEntry);
         mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry));
-        verify(mNotifInflater).inflateViews(eq(mEntry), any(), mCallbackCaptor.capture());
-        mCallbackCaptor.getValue().onInflationFinished(mEntry);
+        verify(mNotifInflater).inflateViews(eq(mEntry), any(), any());
+        mNotifInflater.invokeInflateCallbackForEntry(mEntry);
 
         // THEN it isn't filtered from shade list
         assertFalse(mUninflatedFilter.shouldFilterOut(mEntry, 0));
@@ -347,7 +347,7 @@
         mBeforeFilterListener.onBeforeFinalizeFilter(List.of(group));
 
         // WHEN one of this children finishes inflating
-        mNotifInflater.getInflateCallback(child0).onInflationFinished(child0);
+        mNotifInflater.invokeInflateCallbackForEntry(child0);
 
         // THEN the inflated child is still filtered out
         assertTrue(mUninflatedFilter.shouldFilterOut(child0, 401));
@@ -369,8 +369,8 @@
         mBeforeFilterListener.onBeforeFinalizeFilter(List.of(group));
 
         // WHEN all of the children (but not the summary) finish inflating
-        mNotifInflater.getInflateCallback(child0).onInflationFinished(child0);
-        mNotifInflater.getInflateCallback(child1).onInflationFinished(child1);
+        mNotifInflater.invokeInflateCallbackForEntry(child0);
+        mNotifInflater.invokeInflateCallbackForEntry(child1);
 
         // THEN the entire group is still filtered out
         assertTrue(mUninflatedFilter.shouldFilterOut(summary, 401));
@@ -394,9 +394,9 @@
         mBeforeFilterListener.onBeforeFinalizeFilter(List.of(group));
 
         // WHEN all of the children (and the summary) finish inflating
-        mNotifInflater.getInflateCallback(child0).onInflationFinished(child0);
-        mNotifInflater.getInflateCallback(child1).onInflationFinished(child1);
-        mNotifInflater.getInflateCallback(summary).onInflationFinished(summary);
+        mNotifInflater.invokeInflateCallbackForEntry(child0);
+        mNotifInflater.invokeInflateCallbackForEntry(child1);
+        mNotifInflater.invokeInflateCallbackForEntry(summary);
 
         // THEN the entire group is still filtered out
         assertFalse(mUninflatedFilter.shouldFilterOut(summary, 401));
@@ -418,7 +418,7 @@
         mBeforeFilterListener.onBeforeFinalizeFilter(List.of(group));
 
         // WHEN one of this children finishes inflating and enough time passes
-        mNotifInflater.getInflateCallback(child0).onInflationFinished(child0);
+        mNotifInflater.invokeInflateCallbackForEntry(child0);
 
         // THEN the inflated child is not filtered out even though the rest of the group hasn't
         // finished inflating yet
@@ -446,6 +446,10 @@
         public InflationCallback getInflateCallback(NotificationEntry entry) {
             return requireNonNull(mInflateCallbacks.get(entry));
         }
+
+        public void invokeInflateCallbackForEntry(NotificationEntry entry) {
+            getInflateCallback(entry).onInflationFinished(entry, entry.getRowController());
+        }
     }
 
     private void fireAddEvents(List<? extends ListEntry> entries) {
@@ -470,11 +474,9 @@
     private static final int TEST_CHILD_BIND_CUTOFF = 9;
     private static final int TEST_MAX_GROUP_DELAY = 100;
 
-    private class TestableAdjustmentProvider extends NotifUiAdjustmentProvider {
-        private void setSectionIsLowPriority(boolean lowPriority) {
-            setLowPrioritySections(lowPriority
-                    ? Collections.singleton(mNotifSection.getSectioner())
-                    : Collections.emptyList());
-        }
+    private void setSectionIsLowPriority(boolean minimized) {
+        mSectionClassifier.setMinimizedSections(minimized
+                ? Collections.singleton(mNotifSection.getSectioner())
+                : Collections.emptyList());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
index abe33aa..f4d8405 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
@@ -39,11 +40,11 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.SbnBuilder;
+import com.android.systemui.statusbar.notification.SectionClassifier;
 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.NotificationEntryBuilder;
-import com.android.systemui.statusbar.notification.collection.inflation.NotifUiAdjustmentProvider;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
@@ -67,7 +68,7 @@
 
     @Mock private StatusBarStateController mStatusBarStateController;
     @Mock private HighPriorityProvider mHighPriorityProvider;
-    @Mock private NotifUiAdjustmentProvider mAdjustmentProvider;
+    @Mock private SectionClassifier mSectionClassifier;
     @Mock private NotifPipeline mNotifPipeline;
     @Mock private NodeController mAlertingHeaderController;
     @Mock private NodeController mSilentNodeController;
@@ -91,7 +92,7 @@
         mRankingCoordinator = new RankingCoordinator(
                 mStatusBarStateController,
                 mHighPriorityProvider,
-                mAdjustmentProvider,
+                mSectionClassifier,
                 mAlertingHeaderController,
                 mSilentHeaderController,
                 mSilentNodeController);
@@ -99,6 +100,7 @@
         mEntry.setRanking(getRankingForUnfilteredNotif().build());
 
         mRankingCoordinator.attach(mNotifPipeline);
+        verify(mSectionClassifier).setMinimizedSections(any());
         verify(mNotifPipeline, times(2)).addPreGroupFilter(mNotifFilterCaptor.capture());
         mCapturedSuspendedFilter = mNotifFilterCaptor.getAllValues().get(0);
         mCapturedDozingFilter = mNotifFilterCaptor.getAllValues().get(1);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt
new file mode 100644
index 0000000..52fce13
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RowAppearanceCoordinatorTest.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2021 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 android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.util.Pair
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.AssistantFeedbackController
+import com.android.systemui.statusbar.notification.SectionClassifier
+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.NotifSection
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
+import com.android.systemui.statusbar.notification.collection.render.NotifRowController
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.withArgCaptor
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations.initMocks
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class RowAppearanceCoordinatorTest : SysuiTestCase() {
+    private lateinit var coordinator: RowAppearanceCoordinator
+    private lateinit var beforeRenderListListener: OnBeforeRenderListListener
+    private lateinit var afterRenderEntryListener: OnAfterRenderEntryListener
+
+    private lateinit var entry1: NotificationEntry
+    private lateinit var entry2: NotificationEntry
+
+    @Mock private lateinit var pipeline: NotifPipeline
+    @Mock private lateinit var assistantFeedbackController: AssistantFeedbackController
+    @Mock private lateinit var sectionClassifier: SectionClassifier
+
+    @Mock private lateinit var section1: NotifSection
+    @Mock private lateinit var section2: NotifSection
+    @Mock private lateinit var controller1: NotifRowController
+    @Mock private lateinit var controller2: NotifRowController
+
+    @Before
+    fun setUp() {
+        initMocks(this)
+        coordinator = RowAppearanceCoordinator(
+            mContext,
+            assistantFeedbackController,
+            sectionClassifier
+        )
+        coordinator.attach(pipeline)
+        beforeRenderListListener = withArgCaptor {
+            verify(pipeline).addOnBeforeRenderListListener(capture())
+        }
+        afterRenderEntryListener = withArgCaptor {
+            verify(pipeline).addOnAfterRenderEntryListener(capture())
+        }
+        whenever(assistantFeedbackController.showFeedbackIndicator(any())).thenReturn(true)
+        whenever(assistantFeedbackController.getFeedbackResources(any())).thenReturn(Pair(1, 2))
+        entry1 = NotificationEntryBuilder().setSection(section1).setLastAudiblyAlertedMs(17).build()
+        entry2 = NotificationEntryBuilder().setSection(section2).build()
+    }
+
+    @Test
+    fun testSetSystemExpandedOnlyOnFirst() {
+        whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(false)
+        whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(false)
+        beforeRenderListListener.onBeforeRenderList(listOf(entry1, entry2))
+        afterRenderEntryListener.onAfterRenderEntry(entry1, controller1)
+        verify(controller1).setSystemExpanded(eq(true))
+        afterRenderEntryListener.onAfterRenderEntry(entry2, controller2)
+        verify(controller2).setSystemExpanded(eq(false))
+    }
+
+    @Test
+    fun testSetSystemExpandedNeverIfMinimized() {
+        whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(true)
+        whenever(sectionClassifier.isMinimizedSection(eq(section1))).thenReturn(true)
+        beforeRenderListListener.onBeforeRenderList(listOf(entry1, entry2))
+        afterRenderEntryListener.onAfterRenderEntry(entry1, controller1)
+        verify(controller1).setSystemExpanded(eq(false))
+        afterRenderEntryListener.onAfterRenderEntry(entry2, controller2)
+        verify(controller2).setSystemExpanded(eq(false))
+    }
+
+    @Test
+    fun testSetLastAudiblyAlerted() {
+        afterRenderEntryListener.onAfterRenderEntry(entry1, controller1)
+        verify(controller1).setLastAudiblyAlertedMs(eq(17.toLong()))
+    }
+
+    @Test
+    fun testShowFeedbackIcon() {
+        afterRenderEntryListener.onAfterRenderEntry(entry1, controller1)
+        verify(controller1).showFeedbackIcon(eq(true), eq(Pair(1, 2)))
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
new file mode 100644
index 0000000..70266e4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/StackCoordinatorTest.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 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 android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+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.NotifSection
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
+import com.android.systemui.statusbar.notification.collection.render.NotifStackController
+import com.android.systemui.statusbar.notification.collection.render.NotifStats
+import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
+import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
+import com.android.systemui.statusbar.phone.NotificationIconAreaController
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.withArgCaptor
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations.initMocks
+import org.mockito.Mockito.`when` as whenever
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class StackCoordinatorTest : SysuiTestCase() {
+    private lateinit var coordinator: StackCoordinator
+    private lateinit var afterRenderListListener: OnAfterRenderListListener
+
+    private lateinit var entry: NotificationEntry
+
+    @Mock private lateinit var pipeline: NotifPipeline
+    @Mock private lateinit var notificationIconAreaController: NotificationIconAreaController
+    @Mock private lateinit var stackController: NotifStackController
+    @Mock private lateinit var section: NotifSection
+
+    @Before
+    fun setUp() {
+        initMocks(this)
+        coordinator = StackCoordinator(notificationIconAreaController)
+        coordinator.attach(pipeline)
+        afterRenderListListener = withArgCaptor {
+            verify(pipeline).addOnAfterRenderListListener(capture())
+        }
+        entry = NotificationEntryBuilder().setSection(section).build()
+    }
+
+    @Test
+    fun testUpdateNotificationIcons() {
+        afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+        verify(notificationIconAreaController).updateNotificationIcons(eq(listOf(entry)))
+    }
+
+    @Test
+    fun testSetNotificationStats_clearableAlerting() {
+        whenever(section.bucket).thenReturn(BUCKET_ALERTING)
+        afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+        verify(stackController).setNotifStats(NotifStats(1, false, true, false, false))
+    }
+
+    @Test
+    fun testSetNotificationStats_clearableSilent() {
+        whenever(section.bucket).thenReturn(BUCKET_SILENT)
+        afterRenderListListener.onAfterRenderList(listOf(entry), stackController)
+        verify(stackController).setNotifStats(NotifStats(1, false, false, false, true))
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
index ed48452..5271745 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
@@ -58,6 +58,7 @@
     private val section1 = buildSection(1, section1Bucket, headerController1)
     private val section1NoHeader = buildSection(1, section1Bucket, null)
     private val section2 = buildSection(2, section2Bucket, headerController2)
+    private val section3 = buildSection(3, section2Bucket, headerController2)
 
     private val fakeViewBarn = FakeViewBarn()
 
@@ -67,7 +68,7 @@
     fun setUp() {
         MockitoAnnotations.initMocks(this)
 
-        `when`(viewBarn.requireView(any())).thenAnswer {
+        `when`(viewBarn.requireNodeController(any())).thenAnswer {
             fakeViewBarn.getViewByEntry(it.getArgument(0))
         }
 
@@ -75,6 +76,37 @@
     }
 
     @Test
+    fun testMultipleSectionsWithSameController() {
+        checkOutput(
+                listOf(
+                        notif(0, section0),
+                        notif(1, section2),
+                        notif(2, section3)
+                ),
+                tree(
+                        node(headerController0),
+                        notifNode(0),
+                        node(headerController2),
+                        notifNode(1),
+                        notifNode(2)
+                )
+        )
+    }
+
+    @Test(expected = RuntimeException::class)
+    fun testMultipleSectionsWithSameControllerNonConsecutive() {
+        checkOutput(
+                listOf(
+                        notif(0, section0),
+                        notif(1, section1),
+                        notif(2, section3),
+                        notif(3, section1)
+                ),
+                tree()
+        )
+    }
+
+    @Test
     fun testSimpleMapping() {
         checkOutput(
                 // GIVEN a simple flat list of notifications all in the same headerless section
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
new file mode 100644
index 0000000..70d309b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/RenderStageManagerTest.kt
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2021 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.render
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.GroupEntry
+import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.ShadeListBuilder
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderEntryListener
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderGroupListener
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnAfterRenderListListener
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.withArgCaptor
+import org.junit.Before
+import org.junit.Test
+import org.mockito.Mock
+import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.never
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+class RenderStageManagerTest : SysuiTestCase() {
+
+    @Mock private lateinit var shadeListBuilder: ShadeListBuilder
+    @Mock private lateinit var onAfterRenderListListener: OnAfterRenderListListener
+    @Mock private lateinit var onAfterRenderGroupListener: OnAfterRenderGroupListener
+    @Mock private lateinit var onAfterRenderEntryListener: OnAfterRenderEntryListener
+
+    private lateinit var onRenderListListener: ShadeListBuilder.OnRenderListListener
+    private lateinit var renderStageManager: RenderStageManager
+    private val spyViewRenderer = spy(FakeNotifViewRenderer())
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        renderStageManager = RenderStageManager()
+        renderStageManager.attach(shadeListBuilder)
+        onRenderListListener = withArgCaptor {
+            verify(shadeListBuilder).setOnRenderListListener(capture())
+        }
+    }
+
+    private fun setUpRenderer() {
+        renderStageManager.setViewRenderer(spyViewRenderer)
+    }
+
+    private fun setUpListeners() {
+        renderStageManager.addOnAfterRenderListListener(onAfterRenderListListener)
+        renderStageManager.addOnAfterRenderGroupListener(onAfterRenderGroupListener)
+        renderStageManager.addOnAfterRenderEntryListener(onAfterRenderEntryListener)
+    }
+
+    @Test
+    fun testNoCallbacksWithoutRenderer() {
+        // GIVEN listeners but no renderer
+        setUpListeners()
+
+        // WHEN a shade list is built
+        onRenderListListener.onRenderList(listWith2Groups8Entries())
+
+        // VERIFY that no listeners are called
+        verifyNoMoreInteractions(
+            onAfterRenderListListener,
+            onAfterRenderGroupListener,
+            onAfterRenderEntryListener
+        )
+    }
+
+    @Test
+    fun testDoesNotQueryControllerIfNoListeners() {
+        // GIVEN a renderer but no listeners
+        setUpRenderer()
+
+        // WHEN a shade list is built
+        onRenderListListener.onRenderList(listWith2Groups8Entries())
+
+        // VERIFY that the renderer is not queried for group or row controllers
+        inOrder(spyViewRenderer).apply {
+            verify(spyViewRenderer, times(1)).onRenderList(any())
+            verify(spyViewRenderer, times(1)).getStackController()
+            verify(spyViewRenderer, never()).getGroupController(any())
+            verify(spyViewRenderer, never()).getRowController(any())
+            verify(spyViewRenderer, times(1)).onDispatchComplete()
+            verifyNoMoreInteractions(spyViewRenderer)
+        }
+    }
+
+    @Test
+    fun testDoesQueryControllerIfListeners() {
+        // GIVEN a renderer and listeners
+        setUpRenderer()
+        setUpListeners()
+
+        // WHEN a shade list is built
+        onRenderListListener.onRenderList(listWith2Groups8Entries())
+
+        // VERIFY that the renderer is queried once per group/entry
+        inOrder(spyViewRenderer).apply {
+            verify(spyViewRenderer, times(1)).onRenderList(any())
+            verify(spyViewRenderer, times(1)).getStackController()
+            verify(spyViewRenderer, times(2)).getGroupController(any())
+            verify(spyViewRenderer, times(8)).getRowController(any())
+            verify(spyViewRenderer, times(1)).onDispatchComplete()
+            verifyNoMoreInteractions(spyViewRenderer)
+        }
+    }
+
+    @Test
+    fun testDoesNotQueryControllerTwice() {
+        // GIVEN a renderer and multiple distinct listeners
+        setUpRenderer()
+        setUpListeners()
+        renderStageManager.addOnAfterRenderListListener(mock())
+        renderStageManager.addOnAfterRenderGroupListener(mock())
+        renderStageManager.addOnAfterRenderEntryListener(mock())
+
+        // WHEN a shade list is built
+        onRenderListListener.onRenderList(listWith2Groups8Entries())
+
+        // VERIFY that the renderer is queried once per group/entry
+        inOrder(spyViewRenderer).apply {
+            verify(spyViewRenderer, times(1)).onRenderList(any())
+            verify(spyViewRenderer, times(1)).getStackController()
+            verify(spyViewRenderer, times(2)).getGroupController(any())
+            verify(spyViewRenderer, times(8)).getRowController(any())
+            verify(spyViewRenderer, times(1)).onDispatchComplete()
+            verifyNoMoreInteractions(spyViewRenderer)
+        }
+    }
+
+    @Test
+    fun testDoesCallListenerWithEachGroupAndEntry() {
+        // GIVEN a renderer and multiple distinct listeners
+        setUpRenderer()
+        setUpListeners()
+
+        // WHEN a shade list is built
+        onRenderListListener.onRenderList(listWith2Groups8Entries())
+
+        // VERIFY that the listeners are invoked once per group and once per entry
+        verify(onAfterRenderListListener, times(1)).onAfterRenderList(any(), any())
+        verify(onAfterRenderGroupListener, times(2)).onAfterRenderGroup(any(), any())
+        verify(onAfterRenderEntryListener, times(8)).onAfterRenderEntry(any(), any())
+        verifyNoMoreInteractions(
+            onAfterRenderListListener,
+            onAfterRenderGroupListener,
+            onAfterRenderEntryListener
+        )
+    }
+
+    @Test
+    fun testDoesNotCallGroupAndEntryListenersIfTheListIsEmpty() {
+        // GIVEN a renderer and multiple distinct listeners
+        setUpRenderer()
+        setUpListeners()
+
+        // WHEN a shade list is built empty
+        onRenderListListener.onRenderList(listOf())
+
+        // VERIFY that the stack listener is invoked once but other listeners are not
+        verify(onAfterRenderListListener, times(1)).onAfterRenderList(any(), any())
+        verify(onAfterRenderGroupListener, never()).onAfterRenderGroup(any(), any())
+        verify(onAfterRenderEntryListener, never()).onAfterRenderEntry(any(), any())
+        verifyNoMoreInteractions(
+            onAfterRenderListListener,
+            onAfterRenderGroupListener,
+            onAfterRenderEntryListener
+        )
+    }
+
+    private fun listWith2Groups8Entries() = listOf(
+        group(
+            notif(1),
+            notif(2),
+            notif(3)
+        ),
+        notif(4),
+        group(
+            notif(5),
+            notif(6),
+            notif(7)
+        ),
+        notif(8)
+    )
+
+    private class FakeNotifViewRenderer : NotifViewRenderer {
+        override fun onRenderList(notifList: List<ListEntry>) {}
+        override fun getStackController(): NotifStackController = mock()
+        override fun getGroupController(group: GroupEntry): NotifGroupController = mock()
+        override fun getRowController(entry: NotificationEntry): NotifRowController = mock()
+        override fun onDispatchComplete() {}
+    }
+
+    private fun notif(id: Int): NotificationEntry = NotificationEntryBuilder().setId(id).build()
+
+    private fun group(summary: NotificationEntry, vararg children: NotificationEntry): GroupEntry =
+        GroupEntryBuilder().setSummary(summary).setChildren(children.toList()).build()
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerLegacyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerLegacyTest.java
index 4cf530e..395aec3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerLegacyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerLegacyTest.java
@@ -41,10 +41,10 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -81,7 +81,7 @@
     @Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger;
 
     // Dependency mocks:
-    @Mock private FeatureFlags mFeatureFlags;
+    @Mock private NotifPipelineFlags mNotifPipelineFlags;
     @Mock private NotificationVisibilityProvider mVisibilityProvider;
     @Mock private NotificationEntryManager mEntryManager;
     @Mock private NotifPipeline mNotifPipeline;
@@ -111,7 +111,7 @@
         mLogger = new TestableNotificationLogger(
                 mListener,
                 mUiBgExecutor,
-                mFeatureFlags,
+                mNotifPipelineFlags,
                 mVisibilityProvider,
                 mEntryManager,
                 mNotifPipeline,
@@ -253,7 +253,7 @@
 
         TestableNotificationLogger(NotificationListener notificationListener,
                 Executor uiBgExecutor,
-                FeatureFlags featureFlags,
+                NotifPipelineFlags notifPipelineFlags,
                 NotificationVisibilityProvider visibilityProvider,
                 NotificationEntryManager entryManager,
                 NotifPipeline notifPipeline,
@@ -263,7 +263,7 @@
             super(
                     notificationListener,
                     uiBgExecutor,
-                    featureFlags,
+                    notifPipelineFlags,
                     visibilityProvider,
                     entryManager,
                     notifPipeline,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
index ba198ef..3a9b297 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationLoggerTest.java
@@ -41,10 +41,10 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.StatusBarStateControllerImpl;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -81,7 +81,7 @@
     @Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger;
 
     // Dependency mocks:
-    @Mock private FeatureFlags mFeatureFlags;
+    @Mock private NotifPipelineFlags mNotifPipelineFlags;
     @Mock private NotificationVisibilityProvider mVisibilityProvider;
     @Mock private NotificationEntryManager mEntryManager;
     @Mock private NotifPipeline mNotifPipeline;
@@ -97,7 +97,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(true);
+        when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(true);
 
         mEntry = new NotificationEntryBuilder()
                 .setPkg(TEST_PACKAGE_NAME)
@@ -112,7 +112,7 @@
         mLogger = new TestableNotificationLogger(
                 mListener,
                 mUiBgExecutor,
-                mFeatureFlags,
+                mNotifPipelineFlags,
                 mVisibilityProvider,
                 mEntryManager,
                 mNotifPipeline,
@@ -254,7 +254,7 @@
 
         TestableNotificationLogger(NotificationListener notificationListener,
                 Executor uiBgExecutor,
-                FeatureFlags featureFlags,
+                NotifPipelineFlags notifPipelineFlags,
                 NotificationVisibilityProvider visibilityProvider,
                 NotificationEntryManager entryManager,
                 NotifPipeline notifPipeline,
@@ -264,7 +264,7 @@
             super(
                     notificationListener,
                     uiBgExecutor,
-                    featureFlags,
+                    notifPipelineFlags,
                     visibilityProvider,
                     entryManager,
                     notifPipeline,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
index a53fb78..eeda9dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -48,7 +48,6 @@
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.media.MediaFeatureFlag;
 import com.android.systemui.media.dialog.MediaOutputDialogFactory;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -62,6 +61,7 @@
 import com.android.systemui.statusbar.SmartReplyController;
 import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
 import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationClicker;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
@@ -142,7 +142,7 @@
 
     @Mock private NotificationGroupManagerLegacy mGroupMembershipManager;
     @Mock private NotificationGroupManagerLegacy mGroupExpansionManager;
-    @Mock private FeatureFlags mFeatureFlags;
+    @Mock private NotifPipelineFlags mNotifPipelineFlags;
     @Mock private LeakDetector mLeakDetector;
 
     @Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
@@ -179,12 +179,13 @@
                 .setNotification(notification)
                 .build();
 
-        when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
+        when(mNotifPipelineFlags.checkLegacyPipelineEnabled()).thenReturn(true);
+        when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
 
         mEntryManager = new NotificationEntryManager(
                 mock(NotificationEntryManagerLogger.class),
                 mGroupMembershipManager,
-                mFeatureFlags,
+                mNotifPipelineFlags,
                 () -> mRowBinder,
                 () -> mRemoteInputManager,
                 mLeakDetector,
@@ -282,7 +283,6 @@
 
         mRowBinder = new NotificationRowBinderImpl(
                 mContext,
-                mFeatureFlags,
                 new NotificationMessagingUtil(mContext),
                 mRemoteInputManager,
                 mLockscreenUserManager,
@@ -294,7 +294,8 @@
                         mEntryManager,
                         mock(LauncherApps.class),
                         new IconBuilder(mContext)),
-                mock(LowPriorityInflationHelper.class));
+                mock(LowPriorityInflationHelper.class),
+                mNotifPipelineFlags);
 
         mEntryManager.setUpWithPresenter(mPresenter);
         mEntryManager.addNotificationEntryListener(mEntryListener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index 58e3cc8..276f246 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -52,6 +52,7 @@
 import com.android.systemui.media.KeyguardMediaController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
@@ -80,11 +81,8 @@
     @Rule public final MockitoRule mockitoRule = MockitoJUnit.rule();
 
     @Mock private NotificationStackScrollLayout mNssl;
-    @Mock private FeatureFlags mFeatureFlags;
-    @Mock private ActivityStarterDelegate mActivityStarterDelegate;
     @Mock private StatusBarStateController mStatusBarStateController;
     @Mock private ConfigurationController mConfigurationController;
-    @Mock private PeopleHubViewAdapter mPeopleHubAdapter;
     @Mock private KeyguardMediaController mKeyguardMediaController;
     @Mock private NotificationSectionsFeatureManager mSectionsFeatureManager;
     @Mock private NotificationRowComponent mNotificationRowComponent;
@@ -94,6 +92,7 @@
     @Mock private SectionHeaderController mPeopleHeaderController;
     @Mock private SectionHeaderController mAlertingHeaderController;
     @Mock private SectionHeaderController mSilentHeaderController;
+    @Mock private NotifPipelineFlags mNotifPipelineFlags;
 
     private NotificationSectionsManager mSectionsManager;
 
@@ -122,12 +121,12 @@
         when(mSilentHeaderController.getHeaderView()).thenReturn(mock(SectionHeaderView.class));
         mSectionsManager =
                 new NotificationSectionsManager(
-                        mFeatureFlags,
                         mStatusBarStateController,
                         mConfigurationController,
                         mKeyguardMediaController,
                         mSectionsFeatureManager,
                         mLogger,
+                        mNotifPipelineFlags,
                         mIncomingHeaderController,
                         mPeopleHeaderController,
                         mAlertingHeaderController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index f26bb75..7194c66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -46,7 +46,6 @@
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.media.KeyguardMediaController;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.OnMenuEventListener;
@@ -59,6 +58,7 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
 import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -121,7 +121,7 @@
     @Mock private ScrimController mScrimController;
     @Mock private NotificationGroupManagerLegacy mLegacyGroupManager;
     @Mock private SectionHeaderController mSilentHeaderController;
-    @Mock private FeatureFlags mFeatureFlags;
+    @Mock private NotifPipelineFlags mNotifPipelineFlags;
     @Mock private NotifPipeline mNotifPipeline;
     @Mock private NotifCollection mNotifCollection;
     @Mock private NotificationEntryManager mEntryManager;
@@ -146,7 +146,7 @@
         MockitoAnnotations.initMocks(this);
 
         when(mNotificationSwipeHelperBuilder.build()).thenReturn(mNotificationSwipeHelper);
-        when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
+        when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
         when(mFgServicesSectionController.createView(mLayoutInflater))
                 .thenReturn(mForegroundServiceDungeonView);
 
@@ -176,7 +176,7 @@
                 mLegacyGroupManager,
                 mLegacyGroupManager,
                 mSilentHeaderController,
-                mFeatureFlags,
+                mNotifPipelineFlags,
                 mNotifPipeline,
                 mNotifCollection,
                 mEntryManager,
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 185d9cd..9be2837 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
@@ -30,7 +30,6 @@
 import static org.junit.Assert.assertFalse;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.clearInvocations;
@@ -296,14 +295,10 @@
         setBarStateForTest(StatusBarState.SHADE);
         mStackScroller.setCurrentUserSetup(true);
 
-        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
-        when(row.canViewBeDismissed()).thenReturn(true);
-        when(mStackScroller.getChildCount()).thenReturn(1);
-        when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
         mStackScroller.setIsRemoteInputActive(true);
-        when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
+        when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
+        when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL)))
                 .thenReturn(true);
-        when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
 
         FooterView view = mock(FooterView.class);
         mStackScroller.setFooterView(view);
@@ -312,14 +307,28 @@
     }
 
     @Test
+    public void testUpdateFooter_withoutNotifications() {
+        setBarStateForTest(StatusBarState.SHADE);
+        mStackScroller.setCurrentUserSetup(true);
+
+        when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(0);
+        when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL)))
+                .thenReturn(false);
+
+        FooterView view = mock(FooterView.class);
+        mStackScroller.setFooterView(view);
+        mStackScroller.updateFooter();
+        verify(mStackScroller).updateFooterView(false, false, true);
+    }
+
+    @Test
     public void testUpdateFooter_oneClearableNotification() {
         setBarStateForTest(StatusBarState.SHADE);
         mStackScroller.setCurrentUserSetup(true);
 
-        when(mEmptyShadeView.getVisibility()).thenReturn(GONE);
-        when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
+        when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
+        when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL)))
                 .thenReturn(true);
-        when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
 
         FooterView view = mock(FooterView.class);
         mStackScroller.setFooterView(view);
@@ -332,10 +341,9 @@
         setBarStateForTest(StatusBarState.SHADE);
         mStackScroller.setCurrentUserSetup(false);
 
-        when(mEmptyShadeView.getVisibility()).thenReturn(GONE);
-        when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
+        when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
+        when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL)))
                 .thenReturn(true);
-        when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
 
         FooterView view = mock(FooterView.class);
         mStackScroller.setFooterView(view);
@@ -348,12 +356,8 @@
         setBarStateForTest(StatusBarState.SHADE);
         mStackScroller.setCurrentUserSetup(true);
 
-        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
-        when(row.canViewBeDismissed()).thenReturn(false);
-        when(mStackScroller.getChildCount()).thenReturn(1);
-        when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
-        when(mStackScrollLayoutController.hasActiveNotifications()).thenReturn(true);
-        when(mStackScrollLayoutController.hasActiveClearableNotifications(ROWS_ALL))
+        when(mStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1);
+        when(mStackScrollLayoutController.hasActiveClearableNotifications(eq(ROWS_ALL)))
                 .thenReturn(false);
         when(mEmptyShadeView.getVisibility()).thenReturn(GONE);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
index 0faf5d4..a0e91fc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSwipeHelperTest.java
@@ -438,8 +438,8 @@
         assertEquals("returns false when view is null", false,
                 NotificationSwipeHelper.isTouchInView(mEvent, null));
 
-        doReturn(5f).when(mEvent).getX();
-        doReturn(10f).when(mEvent).getY();
+        doReturn(5f).when(mEvent).getRawX();
+        doReturn(10f).when(mEvent).getRawY();
 
         doReturn(20).when(mView).getWidth();
         doReturn(20).when(mView).getHeight();
@@ -455,7 +455,7 @@
         assertTrue("Touch is within the view",
                 mSwipeHelper.isTouchInView(mEvent, mView));
 
-        doReturn(50f).when(mEvent).getX();
+        doReturn(50f).when(mEvent).getRawX();
 
         assertFalse("Touch is not within the view",
                 mSwipeHelper.isTouchInView(mEvent, mView));
@@ -466,8 +466,8 @@
         assertEquals("returns false when view is null", false,
                 NotificationSwipeHelper.isTouchInView(mEvent, null));
 
-        doReturn(5f).when(mEvent).getX();
-        doReturn(10f).when(mEvent).getY();
+        doReturn(5f).when(mEvent).getRawX();
+        doReturn(10f).when(mEvent).getRawY();
 
         doReturn(20).when(mNotificationRow).getWidth();
         doReturn(20).when(mNotificationRow).getActualHeight();
@@ -483,7 +483,7 @@
         assertTrue("Touch is within the view",
                 mSwipeHelper.isTouchInView(mEvent, mNotificationRow));
 
-        doReturn(50f).when(mEvent).getX();
+        doReturn(50f).when(mEvent).getRawX();
 
         assertFalse("Touch is not within the view",
                 mSwipeHelper.isTouchInView(mEvent, mNotificationRow));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
index 3f5d220..2289936 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/AutoTileManagerTest.java
@@ -51,7 +51,7 @@
 import com.android.systemui.qs.AutoAddTracker;
 import com.android.systemui.qs.QSTileHost;
 import com.android.systemui.qs.ReduceBrightColorsController;
-import com.android.systemui.qs.SecureSetting;
+import com.android.systemui.qs.SettingObserver;
 import com.android.systemui.statusbar.policy.CastController;
 import com.android.systemui.statusbar.policy.CastController.CastDevice;
 import com.android.systemui.statusbar.policy.DataSaverController;
@@ -249,7 +249,7 @@
 
         verify(mWalletController, times(2)).getWalletPosition();
 
-        SecureSetting setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING);
+        SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING);
         assertEquals(USER + 1, setting.getCurrentUser());
         assertTrue(setting.isListening());
     }
@@ -299,7 +299,7 @@
 
         verify(mWalletController, times(2)).getWalletPosition();
 
-        SecureSetting setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING);
+        SettingObserver setting = mAutoTileManager.getSecureSettingForKey(TEST_SETTING);
         assertEquals(USER + 1, setting.getCurrentUser());
         assertFalse(setting.isListening());
     }
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 25fd801..07debe6 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
@@ -45,6 +45,7 @@
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -101,6 +102,8 @@
     private WakefulnessLifecycle mWakefulnessLifecycle;
     @Mock
     private ScreenLifecycle mScreenLifecycle;
+    @Mock
+    private StatusBarStateController mStatusBarStateController;
     private BiometricUnlockController mBiometricUnlockController;
 
     @Before
@@ -123,7 +126,7 @@
                 mUpdateMonitor, res.getResources(), mKeyguardBypassController, mDozeParameters,
                 mMetricsLogger, mDumpManager, mPowerManager,
                 mNotificationMediaManager, mWakefulnessLifecycle, mScreenLifecycle,
-                mAuthController);
+                mAuthController, mStatusBarStateController);
         mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
         mBiometricUnlockController.setBiometricModeListener(mBiometricModeListener);
     }
@@ -378,6 +381,23 @@
     }
 
     @Test
+    public void onUdfpsConsecutivelyFailedThreeTimes_showBouncer() {
+        // GIVEN UDFPS is supported
+        when(mUpdateMonitor.isUdfpsSupported()).thenReturn(true);
+
+        // WHEN udfps fails twice - then don't show the bouncer
+        mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
+        mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
+        verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
+
+        // WHEN udfps fails the third time
+        mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
+
+        // THEN show the bouncer
+        verify(mStatusBarKeyguardViewManager).showBouncer(true);
+    }
+
+    @Test
     public void onFinishedGoingToSleep_authenticatesWhenPending() {
         when(mUpdateMonitor.isGoingToSleep()).thenReturn(true);
         mBiometricUnlockController.onFinishedGoingToSleep(-1);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
deleted file mode 100644
index 75a8624..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentTest.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.android.systemui.statusbar.phone;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.atLeast;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.reset;
-import static org.mockito.Mockito.when;
-
-import android.app.Fragment;
-import android.app.StatusBarManager;
-import android.content.Context;
-import android.os.Bundle;
-import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper.RunWithLooper;
-import android.view.View;
-import android.view.ViewPropertyAnimator;
-import android.widget.FrameLayout;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.R;
-import com.android.systemui.SysuiBaseFragmentTest;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
-import com.android.systemui.log.LogBuffer;
-import com.android.systemui.log.LogcatEchoTracker;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.DisableFlagsLogger;
-import com.android.systemui.statusbar.OperatorNameViewController;
-import com.android.systemui.statusbar.connectivity.NetworkController;
-import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
-import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
-import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.time.FakeSystemClock;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mockito;
-
-import java.util.Optional;
-
-@RunWith(AndroidTestingRunner.class)
-@RunWithLooper(setAsMainLooper = true)
-@SmallTest
-public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
-
-    private NotificationIconAreaController mMockNotificationAreaController;
-    private View mNotificationAreaInner;
-    private OngoingCallController mOngoingCallController;
-    private SystemStatusAnimationScheduler mAnimationScheduler;
-    private StatusBarLocationPublisher mLocationPublisher;
-
-    // Set in instantiate()
-    private StatusBarIconController mStatusBarIconController;
-    private NetworkController mNetworkController;
-    private StatusBarStateController mStatusBarStateController;
-    private KeyguardStateController mKeyguardStateController;
-
-    private final StatusBar mStatusBar = mock(StatusBar.class);
-    private final CommandQueue mCommandQueue = mock(CommandQueue.class);
-    private OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
-    private OperatorNameViewController mOperatorNameViewController;
-
-
-    public CollapsedStatusBarFragmentTest() {
-        super(CollapsedStatusBarFragment.class);
-    }
-
-    @Before
-    public void setup() {
-        mStatusBarStateController = mDependency
-                .injectMockDependency(StatusBarStateController.class);
-        injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
-        when(mStatusBar.getPanelController()).thenReturn(
-                mock(NotificationPanelViewController.class));
-    }
-
-    @Test
-    public void testDisableNone() throws Exception {
-        mFragments.dispatchResume();
-        processAllMessages();
-        CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
-        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
-
-        assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
-                .getVisibility());
-        assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.clock)
-                .getVisibility());
-    }
-
-    @Test
-    public void testDisableSystemInfo() throws Exception {
-        mFragments.dispatchResume();
-        processAllMessages();
-        CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
-        fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_SYSTEM_INFO, 0, false);
-
-        assertEquals(View.INVISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
-                .getVisibility());
-
-        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
-
-        assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.system_icon_area)
-                .getVisibility());
-    }
-
-    @Test
-    public void testDisableNotifications() throws Exception {
-        mFragments.dispatchResume();
-        processAllMessages();
-        CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
-        fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
-
-        Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.INVISIBLE));
-
-        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
-
-        Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE));
-    }
-
-    @Test
-    public void testDisableClock() throws Exception {
-        mFragments.dispatchResume();
-        processAllMessages();
-        CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
-        fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_CLOCK, 0, false);
-
-        assertEquals(View.GONE, mFragment.getView().findViewById(R.id.clock).getVisibility());
-
-        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
-
-        assertEquals(View.VISIBLE, mFragment.getView().findViewById(R.id.clock).getVisibility());
-    }
-
-    @Test
-    public void disable_noOngoingCall_chipHidden() {
-        mFragments.dispatchResume();
-        processAllMessages();
-        CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
-        when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
-
-        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
-
-        assertEquals(View.GONE,
-                mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
-    }
-
-    @Test
-    public void disable_hasOngoingCall_chipDisplayedAndNotificationIconsHidden() {
-        mFragments.dispatchResume();
-        processAllMessages();
-        CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
-        when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
-
-        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
-
-        assertEquals(View.VISIBLE,
-                mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
-        Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.INVISIBLE));
-
-    }
-
-    @Test
-    public void disable_hasOngoingCallButNotificationIconsDisabled_chipHidden() {
-        mFragments.dispatchResume();
-        processAllMessages();
-        CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
-        when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
-
-        fragment.disable(DEFAULT_DISPLAY,
-                StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
-
-        assertEquals(View.GONE,
-                mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
-    }
-
-    @Test
-    public void disable_ongoingCallEnded_chipHidden() {
-        mFragments.dispatchResume();
-        processAllMessages();
-        CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
-        when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
-
-        // Ongoing call started
-        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
-        assertEquals(View.VISIBLE,
-                mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
-
-        // Ongoing call ended
-        when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
-
-        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
-
-        assertEquals(View.GONE,
-                mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
-    }
-
-    @Ignore("b/192618546")
-    @Test
-    public void testOnDozingChanged() throws Exception {
-        mFragments.dispatchResume();
-        processAllMessages();
-        CollapsedStatusBarFragment fragment = (CollapsedStatusBarFragment) mFragment;
-
-        fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
-
-        Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.INVISIBLE));
-
-        reset(mStatusBarStateController);
-        when(mStatusBarStateController.isDozing()).thenReturn(true);
-        fragment.onDozingChanged(true);
-
-        Mockito.verify(mStatusBarStateController).isDozing();
-        Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE));
-    }
-
-    @Override
-    protected Fragment instantiate(Context context, String className, Bundle arguments) {
-        mOngoingCallController = mock(OngoingCallController.class);
-        mAnimationScheduler = mock(SystemStatusAnimationScheduler.class);
-        mLocationPublisher = mock(StatusBarLocationPublisher.class);
-        mStatusBarIconController = mock(StatusBarIconController.class);
-        mNetworkController = mock(NetworkController.class);
-        mStatusBarStateController = mock(StatusBarStateController.class);
-        mKeyguardStateController = mock(KeyguardStateController.class);
-        mOperatorNameViewController = mock(OperatorNameViewController.class);
-        mOperatorNameViewControllerFactory = mock(OperatorNameViewController.Factory.class);
-        when(mOperatorNameViewControllerFactory.create(any()))
-                .thenReturn(mOperatorNameViewController);
-
-        setUpNotificationIconAreaController();
-        return new CollapsedStatusBarFragment(
-                mOngoingCallController,
-                mAnimationScheduler,
-                mLocationPublisher,
-                mMockNotificationAreaController,
-                new PanelExpansionStateManager(),
-                mock(FeatureFlags.class),
-                mStatusBarIconController,
-                new StatusBarHideIconsForBouncerManager(
-                        mCommandQueue, new FakeExecutor(new FakeSystemClock()), new DumpManager()),
-                mKeyguardStateController,
-                mNetworkController,
-                mStatusBarStateController,
-                () -> Optional.of(mStatusBar),
-                mCommandQueue,
-                new CollapsedStatusBarFragmentLogger(
-                        new LogBuffer("TEST", 1, 1, mock(LogcatEchoTracker.class)),
-                        new DisableFlagsLogger()
-                        ),
-                mOperatorNameViewControllerFactory);
-    }
-
-
-    private void setUpNotificationIconAreaController() {
-        mMockNotificationAreaController = mock(NotificationIconAreaController.class);
-
-        mNotificationAreaInner = mock(View.class);
-        View centeredNotificationAreaView = mock(View.class);
-
-        when(mNotificationAreaInner.getLayoutParams()).thenReturn(
-                new FrameLayout.LayoutParams(100, 100));
-        when(centeredNotificationAreaView.getLayoutParams()).thenReturn(
-               new FrameLayout.LayoutParams(100, 100));
-        when(mNotificationAreaInner.animate()).thenReturn(mock(ViewPropertyAnimator.class));
-        when(centeredNotificationAreaView.animate()).thenReturn(mock(ViewPropertyAnimator.class));
-
-        when(mMockNotificationAreaController.getCenteredNotificationAreaView()).thenReturn(
-                centeredNotificationAreaView);
-        when(mMockNotificationAreaController.getNotificationInnerAreaView()).thenReturn(
-                mNotificationAreaInner);
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
index 7a0b366..391a64e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
@@ -39,6 +39,7 @@
 import com.android.systemui.doze.DozeScreenState;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.tuner.TunerService;
 
@@ -126,7 +127,7 @@
     public void testControlUnlockedScreenOffAnimation_dozeAfterScreenOff_false() {
         when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
         mDozeParameters.onTuningChanged(Settings.Secure.DOZE_ALWAYS_ON, "1");
-        when(mFeatureFlags.useNewLockscreenAnimations()).thenReturn(true);
+        when(mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)).thenReturn(true);
         when(mUnlockedScreenOffAnimationController.shouldPlayUnlockedScreenOffAnimation())
                 .thenReturn(true);
         assertTrue(mDozeParameters.shouldControlUnlockedScreenOff());
@@ -143,7 +144,7 @@
     public void testControlUnlockedScreenOffAnimationDisabled_dozeAfterScreenOff() {
         when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
         mDozeParameters.onTuningChanged(Settings.Secure.DOZE_ALWAYS_ON, "1");
-        when(mFeatureFlags.useNewLockscreenAnimations()).thenReturn(false);
+        when(mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)).thenReturn(false);
 
         assertFalse(mDozeParameters.shouldControlUnlockedScreenOff());
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index bafbccd..db5fd26 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -162,8 +162,11 @@
     }
 
     @Test
-    public void testHeaderReadFromOldController() {
-        mHeadsUpAppearanceController.setAppearFraction(1.0f, 1.0f);
+    public void constructor_animationValuesUpdated() {
+        float appearFraction = .75f;
+        float expandedHeight = 400f;
+        when(mStackScrollerController.getAppearFraction()).thenReturn(appearFraction);
+        when(mStackScrollerController.getExpandedHeight()).thenReturn(expandedHeight);
 
         HeadsUpAppearanceController newController = new HeadsUpAppearanceController(
                 mock(NotificationIconAreaController.class),
@@ -179,14 +182,9 @@
                 new View(mContext),
                 new View(mContext),
                 new View(mContext));
-        newController.readFrom(mHeadsUpAppearanceController);
 
-        Assert.assertEquals(mHeadsUpAppearanceController.mExpandedHeight,
-                newController.mExpandedHeight, 0.0f);
-        Assert.assertEquals(mHeadsUpAppearanceController.mAppearFraction,
-                newController.mAppearFraction, 0.0f);
-        Assert.assertEquals(mHeadsUpAppearanceController.mIsExpanded,
-                newController.mIsExpanded);
+        Assert.assertEquals(expandedHeight, newController.mExpandedHeight, 0.0f);
+        Assert.assertEquals(appearFraction, newController.mAppearFraction, 0.0f);
     }
 
     @Test
@@ -195,7 +193,9 @@
         reset(mDarkIconDispatcher);
         reset(mPanelView);
         reset(mStackScrollerController);
-        mHeadsUpAppearanceController.destroy();
+
+        mHeadsUpAppearanceController.onViewDetached();
+
         verify(mHeadsUpManager).removeListener(any());
         verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any());
         verify(mPanelView).removeTrackingHeadsUpListener(any());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
index 210744e..3257a84 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt
@@ -47,8 +47,8 @@
 
     @Test
     fun initFrom_doesntCrash() {
-        val other = LayoutInflater.from(mContext).inflate(
-                R.layout.keyguard_bottom_area, null, false) as KeyguardBottomAreaView
+        val other = LayoutInflater.from(mContext).inflate(R.layout.keyguard_bottom_area,
+                null, false) as KeyguardBottomAreaView
 
         other.initFrom(mKeyguardBottomArea)
         other.launchVoiceAssist()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index 81ddc67..270c64d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -358,6 +358,7 @@
     private NotificationsQuickSettingsContainer mNotificationContainerParent;
     private List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners;
     private FalsingManagerFake mFalsingManager = new FalsingManagerFake();
+    private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
 
     @Before
     public void setup() {
@@ -511,7 +512,7 @@
                 mQuickAccessWalletController,
                 mQrCodeScannerController,
                 mRecordingController,
-                new FakeExecutor(new FakeSystemClock()),
+                mExecutor,
                 mSecureSettings,
                 mSplitShadeHeaderController,
                 mUnlockedScreenOffAnimationController,
@@ -936,6 +937,7 @@
                 ArgumentCaptor.forClass(WeakReference.class);
 
         monitorCallback.getValue().onSourceAvailable(new WeakReference<>(mCommunalSource));
+        mExecutor.runAllReady();
         verify(mCommunalHostViewController).show(sourceCapture.capture());
         assertThat(sourceCapture.getValue().get()).isEqualTo(mCommunalSource);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt
index 4f68a3d..0df7549 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt
@@ -9,6 +9,7 @@
 import com.android.systemui.battery.BatteryMeterView
 import com.android.systemui.battery.BatteryMeterViewController
 import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.flags.Flags
 import com.android.systemui.qs.carrier.QSCarrierGroupController
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
@@ -54,7 +55,7 @@
             null
         }
         whenever(view.visibility).thenAnswer { _ -> viewVisibility }
-        whenever(featureFlags.useCombinedQSHeaders()).thenReturn(false)
+        whenever(featureFlags.isEnabled(Flags.COMBINED_QS_HEADERS)).thenReturn(false)
         splitShadeHeaderController = SplitShadeHeaderController(view, statusBarIconController,
         qsCarrierGroupControllerBuilder, featureFlags, batteryMeterViewController)
     }
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 6f174cb..c5bdfed 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
@@ -374,6 +374,21 @@
     }
 
     @Test
+    public void testHideAltAuth_onShowBouncer() {
+        // GIVEN alt auth is showing
+        mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
+        when(mBouncer.isShowing()).thenReturn(false);
+        when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true);
+        reset(mAlternateAuthInterceptor);
+
+        // WHEN showBouncer is called
+        mStatusBarKeyguardViewManager.showBouncer(true);
+
+        // THEN alt bouncer should be hidden
+        verify(mAlternateAuthInterceptor).hideAlternateAuthBouncer();
+    }
+
+    @Test
     public void testUpdateResources_delegatesToBouncer() {
         mStatusBarKeyguardViewManager.updateResources();
 
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 7791fd0..07ec0e2 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
@@ -35,6 +35,7 @@
 
 import android.app.KeyguardManager;
 import android.app.Notification;
+import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Intent;
 import android.os.Handler;
@@ -54,7 +55,6 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.assist.AssistManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
@@ -63,6 +63,7 @@
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
@@ -116,13 +117,15 @@
     @Mock
     private KeyguardStateController mKeyguardStateController;
     @Mock
+    private NotificationInterruptStateProvider mNotificationInterruptStateProvider;
+    @Mock
     private Handler mHandler;
     @Mock
     private BubblesManager mBubblesManager;
     @Mock
     private ShadeControllerImpl mShadeController;
     @Mock
-    private FeatureFlags mFeatureFlags;
+    private NotifPipelineFlags mNotifPipelineFlags;
     @Mock
     private NotifPipeline mNotifPipeline;
     @Mock
@@ -137,7 +140,7 @@
     @Mock
     private OnUserInteractionCallback mOnUserInteractionCallback;
     @Mock
-    private NotificationActivityStarter mNotificationActivityStarter;
+    private StatusBarNotificationActivityStarter mNotificationActivityStarter;
     @Mock
     private ActivityLaunchAnimator mActivityLaunchAnimator;
     private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -180,7 +183,7 @@
         mActiveNotifications.add(mBubbleNotificationRow.getEntry());
         when(mEntryManager.getVisibleNotifications()).thenReturn(mActiveNotifications);
         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE);
-        when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
+        when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
         when(mOnUserInteractionCallback.getGroupSummaryToDismiss(mNotificationRow.getEntry()))
                 .thenReturn(null);
         when(mVisibilityProvider.obtain(anyString(), anyBoolean())).thenAnswer(
@@ -219,12 +222,12 @@
                         mock(NotificationLockscreenUserManager.class),
                         mShadeController,
                         mKeyguardStateController,
-                        mock(NotificationInterruptStateProvider.class),
+                        mNotificationInterruptStateProvider,
                         mock(LockPatternUtils.class),
                         mock(StatusBarRemoteInputCallback.class),
                         mActivityIntentHelper,
 
-                        mFeatureFlags,
+                        mNotifPipelineFlags,
                         mock(MetricsLogger.class),
                         mock(StatusBarNotificationActivityStarterLogger.class),
                         mOnUserInteractionCallback)
@@ -375,4 +378,27 @@
         // Notification should not be cancelled.
         verify(mEntryManager, never()).performRemoveNotification(eq(sbn), any(), anyInt());
     }
+
+    @Test
+    public void testOnFullScreenIntentWhenDozing_wakeUpDevice() {
+        // GIVEN entry that can has a full screen intent that can show
+        Notification.Builder nb = new Notification.Builder(mContext, "a")
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon)
+                .setFullScreenIntent(mock(PendingIntent.class), true);
+        StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0,
+                "tag" + System.currentTimeMillis(), 0, 0,
+                nb.build(), new UserHandle(0), null, 0);
+        NotificationEntry entry = mock(NotificationEntry.class);
+        when(entry.getImportance()).thenReturn(NotificationManager.IMPORTANCE_HIGH);
+        when(entry.getSbn()).thenReturn(sbn);
+        when(mNotificationInterruptStateProvider.shouldLaunchFullScreenIntentWhenAdded(eq(entry)))
+                .thenReturn(true);
+
+        // WHEN
+        mNotificationActivityStarter.handleFullScreenIntent(entry);
+
+        // THEN display should try wake up for the full screen intent
+        verify(mStatusBar).wakeUpForFullScreenIntent();
+    }
 }
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 4e6b0a2..7d9e6b4 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
@@ -37,7 +37,6 @@
 import com.android.systemui.ForegroundServiceNotificationListener;
 import com.android.systemui.InitController;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -49,6 +48,7 @@
 import com.android.systemui.statusbar.NotificationViewHierarchyManager;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -112,7 +112,6 @@
                 mock(NotificationShadeWindowController.class), mock(DynamicPrivacyController.class),
                 mock(KeyguardStateController.class),
                 mock(KeyguardIndicationController.class),
-                mock(FeatureFlags.class),
                 mStatusBar,
                 mock(ShadeControllerImpl.class), mock(LockscreenShadeTransitionController.class),
                 mCommandQueue,
@@ -128,7 +127,8 @@
                 mInitController,
                 mNotificationInterruptStateProvider,
                 mock(NotificationRemoteInputManager.class),
-                mock(ConfigurationController.class));
+                mock(ConfigurationController.class),
+                mock(NotifPipelineFlags.class));
         mInitController.executePostInitTasks();
         ArgumentCaptor<NotificationInterruptSuppressor> suppressorCaptor =
                 ArgumentCaptor.forClass(NotificationInterruptSuppressor.class);
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 371b91f..a34d2f5 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
@@ -77,6 +77,7 @@
 import com.android.systemui.InitController;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.accessibility.floatingmenu.AccessibilityFloatingMenuController;
 import com.android.systemui.animation.ActivityLaunchAnimator;
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -86,6 +87,7 @@
 import com.android.systemui.demomode.DemoModeController;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.fragments.FragmentService;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.keyguard.ScreenLifecycle;
@@ -114,6 +116,7 @@
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationFilter;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
@@ -133,6 +136,7 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
+import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragmentLogger;
 import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -207,6 +211,7 @@
     @Mock private AmbientDisplayConfiguration mAmbientDisplayConfiguration;
     @Mock private NotificationLogger.ExpansionStateLogger mExpansionStateLogger;
     @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    @Mock private StatusBarSignalPolicy mStatusBarSignalPolicy;
     @Mock private NotificationShadeWindowView mNotificationShadeWindowView;
     @Mock private BroadcastDispatcher mBroadcastDispatcher;
     @Mock private AssistManager mAssistManager;
@@ -215,6 +220,7 @@
     @Mock private NotificationGutsManager mNotificationGutsManager;
     @Mock private NotificationMediaManager mNotificationMediaManager;
     @Mock private NavigationBarController mNavigationBarController;
+    @Mock private AccessibilityFloatingMenuController mAccessibilityFloatingMenuController;
     @Mock private BypassHeadsUpNotifier mBypassHeadsUpNotifier;
     @Mock private SysuiColorExtractor mColorExtractor;
     @Mock private ColorExtractor.GradientColors mGradientColors;
@@ -275,8 +281,8 @@
     @Mock private StartingSurface mStartingSurface;
     @Mock private OperatorNameViewController mOperatorNameViewController;
     @Mock private OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
-    @Mock private PhoneStatusBarViewController.Factory mPhoneStatusBarViewControllerFactory;
     @Mock private ActivityLaunchAnimator mActivityLaunchAnimator;
+    @Mock private NotifPipelineFlags mNotifPipelineFlags;
     private ShadeController mShadeController;
     private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
     private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
@@ -308,7 +314,7 @@
         NotificationLogger notificationLogger = new NotificationLogger(
                 mNotificationListener,
                 mUiBgExecutor,
-                mFeatureFlags,
+                mNotifPipelineFlags,
                 mVisibilityProvider,
                 mock(NotificationEntryManager.class),
                 mock(NotifPipeline.class),
@@ -370,10 +376,12 @@
         mStatusBar = new StatusBar(
                 mContext,
                 mNotificationsController,
+                mock(FragmentService.class),
                 mLightBarController,
                 mAutoHideController,
                 mStatusBarWindowController,
                 mKeyguardUpdateMonitor,
+                mStatusBarSignalPolicy,
                 mPulseExpansionHandler,
                 mNotificationWakeUpCoordinator,
                 mKeyguardBypassController,
@@ -410,6 +418,7 @@
                 mVisualStabilityManager,
                 mDeviceProvisionedController,
                 mNavigationBarController,
+                mAccessibilityFloatingMenuController,
                 () -> mAssistManager,
                 configurationController,
                 mNotificationShadeWindowController,
@@ -439,7 +448,6 @@
                 mExtensionController,
                 mUserInfoControllerImpl,
                 mOperatorNameViewControllerFactory,
-                mPhoneStatusBarViewControllerFactory,
                 mPhoneStatusBarPolicy,
                 mKeyguardIndicationController,
                 mDemoModeController,
@@ -464,7 +472,8 @@
                 Optional.of(mStartingSurface),
                 mTunerService,
                 mDumpManager,
-                mActivityLaunchAnimator);
+                mActivityLaunchAnimator,
+                mNotifPipelineFlags);
         when(mKeyguardViewMediator.registerStatusBar(
                 any(StatusBar.class),
                 any(NotificationPanelViewController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
similarity index 97%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLoggerTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
index bf8cc37..1ee8875 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CollapsedStatusBarFragmentLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentLoggerTest.kt
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.phone
+package com.android.systemui.statusbar.phone.fragment
 
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
new file mode 100644
index 0000000..526f5b7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone.fragment;
+
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.app.Fragment;
+import android.app.StatusBarManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.View;
+import android.view.ViewPropertyAnimator;
+import android.widget.FrameLayout;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiBaseFragmentTest;
+import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.log.LogBuffer;
+import com.android.systemui.log.LogcatEchoTracker;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.DisableFlagsLogger;
+import com.android.systemui.statusbar.OperatorNameViewController;
+import com.android.systemui.statusbar.connectivity.NetworkController;
+import com.android.systemui.statusbar.events.SystemStatusAnimationScheduler;
+import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
+import com.android.systemui.statusbar.phone.NotificationPanelViewController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarLocationPublisher;
+import com.android.systemui.statusbar.phone.fragment.dagger.StatusBarFragmentComponent;
+import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
+import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+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.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Optional;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper(setAsMainLooper = true)
+@SmallTest
+public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
+
+    private NotificationIconAreaController mMockNotificationAreaController;
+    private View mNotificationAreaInner;
+    private OngoingCallController mOngoingCallController;
+    private SystemStatusAnimationScheduler mAnimationScheduler;
+    private StatusBarLocationPublisher mLocationPublisher;
+    // Set in instantiate()
+    private StatusBarIconController mStatusBarIconController;
+    private NetworkController mNetworkController;
+    private KeyguardStateController mKeyguardStateController;
+
+    private final StatusBar mStatusBar = mock(StatusBar.class);
+    private final CommandQueue mCommandQueue = mock(CommandQueue.class);
+    private OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
+    private OperatorNameViewController mOperatorNameViewController;
+
+    @Mock
+    private StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory;
+    @Mock
+    private StatusBarFragmentComponent mStatusBarFragmentComponent;
+    @Mock
+    private StatusBarStateController mStatusBarStateController;
+    @Mock
+    private HeadsUpAppearanceController mHeadsUpAppearanceController;
+    @Mock
+    private NotificationPanelViewController mNotificationPanelViewController;
+
+    public CollapsedStatusBarFragmentTest() {
+        super(CollapsedStatusBarFragment.class);
+    }
+
+    @Before
+    public void setup() {
+        injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
+    }
+
+    @Test
+    public void testDisableNone() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.VISIBLE, getClockView().getVisibility());
+    }
+
+    @Test
+    public void testDisableSystemInfo() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+
+        fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_SYSTEM_INFO, 0, false);
+
+        assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility());
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+    }
+
+    @Test
+    public void testDisableNotifications() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+
+        fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
+
+        Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.INVISIBLE));
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.VISIBLE));
+    }
+
+    @Test
+    public void testDisableClock() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+
+        fragment.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_CLOCK, 0, false);
+
+        assertEquals(View.GONE, getClockView().getVisibility());
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        assertEquals(View.VISIBLE, getClockView().getVisibility());
+    }
+
+    @Test
+    public void disable_noOngoingCall_chipHidden() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+
+        when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        assertEquals(View.GONE,
+                mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
+    }
+
+    @Test
+    public void disable_hasOngoingCall_chipDisplayedAndNotificationIconsHidden() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+
+        when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        assertEquals(View.VISIBLE,
+                mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
+        Mockito.verify(mNotificationAreaInner, atLeast(1)).setVisibility(eq(View.INVISIBLE));
+
+    }
+
+    @Test
+    public void disable_hasOngoingCallButNotificationIconsDisabled_chipHidden() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+
+        when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
+
+        fragment.disable(DEFAULT_DISPLAY,
+                StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
+
+        assertEquals(View.GONE,
+                mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
+    }
+
+    @Test
+    public void disable_ongoingCallEnded_chipHidden() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+
+        when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
+
+        // Ongoing call started
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+        assertEquals(View.VISIBLE,
+                mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
+
+        // Ongoing call ended
+        when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        assertEquals(View.GONE,
+                mFragment.getView().findViewById(R.id.ongoing_call_chip).getVisibility());
+    }
+
+    @Test
+    public void disable_isDozingButNoCustomClock_clockAndSystemInfoVisible() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+        when(mStatusBarStateController.isDozing()).thenReturn(true);
+        when(mNotificationPanelViewController.hasCustomClock()).thenReturn(false);
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.VISIBLE, getClockView().getVisibility());
+    }
+
+    @Test
+    public void disable_customClockButNotDozing_clockAndSystemInfoVisible() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+        when(mStatusBarStateController.isDozing()).thenReturn(false);
+        when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.VISIBLE, getClockView().getVisibility());
+    }
+
+    @Test
+    public void disable_dozingAndCustomClock_clockAndSystemInfoHidden() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+        when(mStatusBarStateController.isDozing()).thenReturn(true);
+        when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
+
+        // Make sure they start out as visible
+        assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.VISIBLE, getClockView().getVisibility());
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.GONE, getClockView().getVisibility());
+    }
+
+    @Test
+    public void onDozingChanged_clockAndSystemInfoVisibilitiesUpdated() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+        when(mStatusBarStateController.isDozing()).thenReturn(true);
+        when(mNotificationPanelViewController.hasCustomClock()).thenReturn(true);
+
+        // Make sure they start out as visible
+        assertEquals(View.VISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.VISIBLE, getClockView().getVisibility());
+
+        fragment.onDozingChanged(true);
+
+        // When this callback is triggered, we want to make sure the clock and system info
+        // visibilities are recalculated. Since dozing=true, they shouldn't be visible.
+        assertEquals(View.INVISIBLE, getSystemIconAreaView().getVisibility());
+        assertEquals(View.GONE, getClockView().getVisibility());
+    }
+
+    @Test
+    public void disable_headsUpShouldBeVisibleTrue_clockDisabled() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+        when(mHeadsUpAppearanceController.shouldBeVisible()).thenReturn(true);
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        assertEquals(View.GONE, getClockView().getVisibility());
+    }
+
+    @Test
+    public void disable_headsUpShouldBeVisibleFalse_clockNotDisabled() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+        when(mHeadsUpAppearanceController.shouldBeVisible()).thenReturn(false);
+
+        fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
+
+        assertEquals(View.VISIBLE, getClockView().getVisibility());
+    }
+
+    @Test
+    public void setUp_fragmentCreatesDaggerComponent() {
+        CollapsedStatusBarFragment fragment = resumeAndGetFragment();
+
+        assertEquals(mStatusBarFragmentComponent, fragment.getStatusBarFragmentComponent());
+    }
+
+    @Override
+    protected Fragment instantiate(Context context, String className, Bundle arguments) {
+        MockitoAnnotations.initMocks(this);
+        setUpDaggerComponent();
+        mOngoingCallController = mock(OngoingCallController.class);
+        mAnimationScheduler = mock(SystemStatusAnimationScheduler.class);
+        mLocationPublisher = mock(StatusBarLocationPublisher.class);
+        mStatusBarIconController = mock(StatusBarIconController.class);
+        mNetworkController = mock(NetworkController.class);
+        mStatusBarStateController = mock(StatusBarStateController.class);
+        mKeyguardStateController = mock(KeyguardStateController.class);
+        mOperatorNameViewController = mock(OperatorNameViewController.class);
+        mOperatorNameViewControllerFactory = mock(OperatorNameViewController.Factory.class);
+        when(mOperatorNameViewControllerFactory.create(any()))
+                .thenReturn(mOperatorNameViewController);
+
+        setUpNotificationIconAreaController();
+        return new CollapsedStatusBarFragment(
+                mStatusBarFragmentComponentFactory,
+                mOngoingCallController,
+                mAnimationScheduler,
+                mLocationPublisher,
+                mMockNotificationAreaController,
+                new PanelExpansionStateManager(),
+                mock(FeatureFlags.class),
+                mStatusBarIconController,
+                new StatusBarHideIconsForBouncerManager(
+                        mCommandQueue, new FakeExecutor(new FakeSystemClock()), new DumpManager()),
+                mKeyguardStateController,
+                mNotificationPanelViewController,
+                mNetworkController,
+                mStatusBarStateController,
+                () -> Optional.of(mStatusBar),
+                mCommandQueue,
+                new CollapsedStatusBarFragmentLogger(
+                        new LogBuffer("TEST", 1, 1, mock(LogcatEchoTracker.class)),
+                        new DisableFlagsLogger()
+                        ),
+                mOperatorNameViewControllerFactory);
+    }
+
+    private void setUpDaggerComponent() {
+        when(mStatusBarFragmentComponentFactory.create(any()))
+                .thenReturn(mStatusBarFragmentComponent);
+        when(mStatusBarFragmentComponent.getHeadsUpAppearanceController())
+                .thenReturn(mHeadsUpAppearanceController);
+    }
+
+    private void setUpNotificationIconAreaController() {
+        mMockNotificationAreaController = mock(NotificationIconAreaController.class);
+
+        mNotificationAreaInner = mock(View.class);
+        View centeredNotificationAreaView = mock(View.class);
+
+        when(mNotificationAreaInner.getLayoutParams()).thenReturn(
+                new FrameLayout.LayoutParams(100, 100));
+        when(centeredNotificationAreaView.getLayoutParams()).thenReturn(
+               new FrameLayout.LayoutParams(100, 100));
+        when(mNotificationAreaInner.animate()).thenReturn(mock(ViewPropertyAnimator.class));
+        when(centeredNotificationAreaView.animate()).thenReturn(mock(ViewPropertyAnimator.class));
+
+        when(mMockNotificationAreaController.getCenteredNotificationAreaView()).thenReturn(
+                centeredNotificationAreaView);
+        when(mMockNotificationAreaController.getNotificationInnerAreaView()).thenReturn(
+                mNotificationAreaInner);
+    }
+
+    private CollapsedStatusBarFragment resumeAndGetFragment() {
+        mFragments.dispatchResume();
+        processAllMessages();
+        return (CollapsedStatusBarFragment) mFragment;
+    }
+
+    private View getClockView() {
+        return mFragment.getView().findViewById(R.id.clock);
+    }
+
+    private View getSystemIconAreaView() {
+        return mFragment.getView().findViewById(R.id.system_icon_area);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
index b385b7d..0920cac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt
@@ -35,7 +35,6 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.plugins.statusbar.StatusBarStateController
 import com.android.systemui.statusbar.gesture.SwipeStatusBarAwayGestureHandler
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
@@ -62,7 +61,7 @@
 import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
-import java.util.Optional
+import java.util.*
 
 private const val CALL_UID = 900
 
@@ -84,7 +83,7 @@
     private lateinit var controller: OngoingCallController
     private lateinit var notifCollectionListener: NotifCollectionListener
 
-    @Mock private lateinit var mockFeatureFlags: FeatureFlags
+    @Mock private lateinit var mockOngoingCallFlags: OngoingCallFlags
     @Mock private lateinit var mockSwipeStatusBarAwayGestureHandler: SwipeStatusBarAwayGestureHandler
     @Mock private lateinit var mockOngoingCallListener: OngoingCallListener
     @Mock private lateinit var mockActivityStarter: ActivityStarter
@@ -102,12 +101,12 @@
         }
 
         MockitoAnnotations.initMocks(this)
-        `when`(mockFeatureFlags.isOngoingCallStatusBarChipEnabled).thenReturn(true)
+        `when`(mockOngoingCallFlags.isStatusBarChipEnabled()).thenReturn(true)
         val notificationCollection = mock(CommonNotifCollection::class.java)
 
         controller = OngoingCallController(
                 notificationCollection,
-                mockFeatureFlags,
+                mockOngoingCallFlags,
                 clock,
                 mockActivityStarter,
                 mainExecutor,
@@ -449,7 +448,7 @@
 
     @Test
     fun fullscreenIsTrue_thenCallNotificationAdded_chipNotClickable() {
-        `when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(false)
+        `when`(mockOngoingCallFlags.isInImmersiveChipTapEnabled()).thenReturn(false)
 
         getStateListener().onFullscreenStateChanged(/* isFullscreen= */ true)
         notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
@@ -459,7 +458,7 @@
 
     @Test
     fun callNotificationAdded_thenFullscreenIsTrue_chipNotClickable() {
-        `when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(false)
+        `when`(mockOngoingCallFlags.isInImmersiveChipTapEnabled()).thenReturn(false)
 
         notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
         getStateListener().onFullscreenStateChanged(/* isFullscreen= */ true)
@@ -469,7 +468,7 @@
 
     @Test
     fun fullscreenChangesToFalse_chipClickable() {
-        `when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(false)
+        `when`(mockOngoingCallFlags.isInImmersiveChipTapEnabled()).thenReturn(false)
 
         notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
         // First, update to true
@@ -482,7 +481,7 @@
 
     @Test
     fun fullscreenIsTrue_butChipClickInImmersiveEnabled_chipClickable() {
-        `when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(true)
+        `when`(mockOngoingCallFlags.isInImmersiveChipTapEnabled()).thenReturn(true)
 
         notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
         getStateListener().onFullscreenStateChanged(/* isFullscreen= */ true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
index 27ddb36..ba7bbfe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
@@ -46,6 +46,7 @@
 import android.widget.EditText;
 import android.widget.ImageButton;
 
+import androidx.annotation.NonNull;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.logging.UiEventLogger;
@@ -55,6 +56,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.RemoteInputController;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
 import com.android.systemui.statusbar.phone.LightBarController;
@@ -85,7 +87,6 @@
     @Mock private LightBarController mLightBarController;
     private BlockingQueueIntentReceiver mReceiver;
     private final UiEventLoggerFake mUiEventLoggerFake = new UiEventLoggerFake();
-    private RemoteInputView mView;
 
     @Before
     public void setUp() throws Exception {
@@ -112,13 +113,17 @@
         mContext.unregisterReceiver(mReceiver);
     }
 
-    private void setTestPendingIntent(RemoteInputView view) {
+    private void setTestPendingIntent(RemoteInputView view, RemoteInputViewController controller) {
         PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0,
                 new Intent(TEST_ACTION), PendingIntent.FLAG_MUTABLE);
         RemoteInput input = new RemoteInput.Builder(TEST_RESULT_KEY).build();
+        RemoteInput[] inputs = {input};
 
         view.setPendingIntent(pendingIntent);
-        view.setRemoteInput(new RemoteInput[]{input}, input, null /* editedSuggestionInfo */);
+        controller.setPendingIntent(pendingIntent);
+        view.setRemoteInput(inputs, input, null /* editedSuggestionInfo */);
+        controller.setRemoteInput(input);
+        controller.setRemoteInputs(inputs);
     }
 
     @Test
@@ -129,8 +134,9 @@
                 TestableLooper.get(this));
         ExpandableNotificationRow row = helper.createRow();
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
+        RemoteInputViewController controller = bindController(view, row.getEntry());
 
-        setTestPendingIntent(view);
+        setTestPendingIntent(view, controller);
 
         view.focus();
 
@@ -140,6 +146,7 @@
         sendButton.performClick();
 
         Intent resultIntent = mReceiver.waitForIntent();
+        assertNotNull(resultIntent);
         assertEquals(TEST_REPLY,
                 RemoteInput.getResultsFromIntent(resultIntent).get(TEST_RESULT_KEY));
         assertEquals(RemoteInput.SOURCE_FREE_FORM_INPUT,
@@ -167,8 +174,9 @@
                 UserHandle.getUid(fromUser.getIdentifier(), DUMMY_MESSAGE_APP_ID),
                 toUser);
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
+        RemoteInputViewController controller = bindController(view, row.getEntry());
 
-        setTestPendingIntent(view);
+        setTestPendingIntent(view, controller);
 
         view.focus();
 
@@ -224,8 +232,9 @@
                 TestableLooper.get(this));
         ExpandableNotificationRow row = helper.createRow();
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
+        RemoteInputViewController controller = bindController(view, row.getEntry());
 
-        setTestPendingIntent(view);
+        setTestPendingIntent(view, controller);
 
         // Open view, send a reply
         view.focus();
@@ -253,8 +262,9 @@
                 TestableLooper.get(this));
         ExpandableNotificationRow row = helper.createRow();
         RemoteInputView view = RemoteInputView.inflate(mContext, null, row.getEntry(), mController);
+        RemoteInputViewController controller = bindController(view, row.getEntry());
 
-        setTestPendingIntent(view);
+        setTestPendingIntent(view, controller);
 
         // Open view, attach an image
         view.focus();
@@ -279,4 +289,21 @@
                         .NOTIFICATION_REMOTE_INPUT_ATTACH_IMAGE.getId(),
                 mUiEventLoggerFake.eventId(1));
     }
+
+    // NOTE: because we're refactoring the RemoteInputView and moving logic into the
+    //  RemoteInputViewController, it's easiest to just test the system of the two classes together.
+    @NonNull
+    private RemoteInputViewController bindController(
+            RemoteInputView view,
+            NotificationEntry entry) {
+        RemoteInputViewControllerImpl viewController = new RemoteInputViewControllerImpl(
+                view,
+                entry,
+                mRemoteInputQuickSettingsDisabler,
+                mController,
+                mShortcutManager,
+                mUiEventLoggerFake);
+        viewController.bind();
+        return viewController;
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
index 379c595..25fafa1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/UserSwitcherControllerTest.kt
@@ -31,6 +31,7 @@
 import android.os.UserManager
 import android.testing.AndroidTestingRunner
 import android.testing.TestableLooper
+import android.view.ThreadedRenderer
 import androidx.test.filters.SmallTest
 import com.android.internal.jank.InteractionJankMonitor
 import com.android.internal.logging.testing.UiEventLoggerFake
@@ -44,13 +45,16 @@
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.qs.QSUserSwitcherEvent
+import com.android.systemui.qs.user.UserSwitchDialogController
 import com.android.systemui.settings.UserTracker
+import com.android.systemui.statusbar.phone.NotificationShadeWindowView
 import com.android.systemui.telephony.TelephonyListenerManager
 import com.android.systemui.util.concurrency.FakeExecutor
 import com.android.systemui.util.settings.SecureSettings
 import com.android.systemui.util.time.FakeSystemClock
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertFalse
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -60,6 +64,8 @@
 import org.mockito.Mockito.`when`
 import org.mockito.Mockito.any
 import org.mockito.Mockito.anyString
+import org.mockito.Mockito.doNothing
+import org.mockito.Mockito.doReturn
 import org.mockito.Mockito.mock
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
@@ -85,6 +91,9 @@
     @Mock private lateinit var dumpManager: DumpManager
     @Mock private lateinit var interactionJankMonitor: InteractionJankMonitor
     @Mock private lateinit var latencyTracker: LatencyTracker
+    @Mock private lateinit var dialogShower: UserSwitchDialogController.DialogShower
+    @Mock private lateinit var notificationShadeWindowView: NotificationShadeWindowView
+    @Mock private lateinit var threadedRenderer: ThreadedRenderer
     private lateinit var testableLooper: TestableLooper
     private lateinit var uiBgExecutor: FakeExecutor
     private lateinit var uiEventLogger: UiEventLoggerFake
@@ -98,6 +107,8 @@
     private val guestId = 1234
     private val guestInfo = UserInfo(guestId, "Guest", null,
             UserInfo.FLAG_FULL or UserInfo.FLAG_GUEST, UserManager.USER_TYPE_FULL_GUEST)
+    private val secondaryUser =
+            UserInfo(10, "Secondary", null, 0, UserManager.USER_TYPE_FULL_SECONDARY)
 
     @Before
     fun setUp() {
@@ -113,7 +124,9 @@
         mContext.addMockSystemService(Context.FINGERPRINT_SERVICE,
                 mock(FingerprintManager::class.java))
 
-        `when`(userManager.canAddMoreUsers()).thenReturn(true)
+        `when`(userManager.canAddMoreUsers(eq(UserManager.USER_TYPE_FULL_SECONDARY)))
+                .thenReturn(true)
+        `when`(notificationShadeWindowView.context).thenReturn(context)
 
         userSwitcherController = UserSwitcherController(
                 context,
@@ -138,7 +151,37 @@
                 dumpManager)
         userSwitcherController.mPauseRefreshUsers = true
 
+        // Since userSwitcherController involves InteractionJankMonitor.
+        // Let's fulfill the dependencies.
+        val mockedContext = mock(Context::class.java)
+        doReturn(mockedContext).`when`(notificationShadeWindowView).context
+        doReturn(true).`when`(notificationShadeWindowView).isAttachedToWindow
+        doNothing().`when`(threadedRenderer).addObserver(any())
+        doNothing().`when`(threadedRenderer).removeObserver(any())
+        doReturn(threadedRenderer).`when`(notificationShadeWindowView).threadedRenderer
+        userSwitcherController.init(notificationShadeWindowView)
+
         picture = UserIcons.convertToBitmap(context.getDrawable(R.drawable.ic_avatar_user))
+        userSwitcherController.init(notificationShadeWindowView)
+    }
+
+    @Test
+    fun testSwitchUser_parentDialogDismissed() {
+        val otherUserRecord = UserSwitcherController.UserRecord(
+                secondaryUser,
+                picture,
+                false /* guest */,
+                false /* current */,
+                false /* isAddUser */,
+                false /* isRestricted */,
+                true /* isSwitchToEnabled */)
+        `when`(userTracker.userId).thenReturn(ownerId)
+        `when`(userTracker.userInfo).thenReturn(ownerInfo)
+
+        userSwitcherController.onUserListItemClicked(otherUserRecord, dialogShower)
+        testableLooper.processAllMessages()
+
+        verify(dialogShower).dismiss()
     }
 
     @Test
@@ -156,7 +199,7 @@
 
         `when`(userManager.createGuest(any(), anyString())).thenReturn(guestInfo)
 
-        userSwitcherController.onUserListItemClicked(emptyGuestUserRecord)
+        userSwitcherController.onUserListItemClicked(emptyGuestUserRecord, null)
         testableLooper.processAllMessages()
         verify(interactionJankMonitor).begin(any())
         verify(latencyTracker).onActionStart(LatencyTracker.ACTION_USER_SWITCH)
@@ -166,6 +209,26 @@
     }
 
     @Test
+    fun testAddGuest_parentDialogDismissed() {
+        val emptyGuestUserRecord = UserSwitcherController.UserRecord(
+                null,
+                null,
+                true /* guest */,
+                false /* current */,
+                false /* isAddUser */,
+                false /* isRestricted */,
+                true /* isSwitchToEnabled */)
+        `when`(userTracker.userId).thenReturn(ownerId)
+        `when`(userTracker.userInfo).thenReturn(ownerInfo)
+
+        `when`(userManager.createGuest(any(), anyString())).thenReturn(guestInfo)
+
+        userSwitcherController.onUserListItemClicked(emptyGuestUserRecord, dialogShower)
+        testableLooper.processAllMessages()
+        verify(dialogShower).dismiss()
+    }
+
+    @Test
     fun testRemoveGuest_removeButtonPressed_isLogged() {
         val currentGuestUserRecord = UserSwitcherController.UserRecord(
                 guestInfo,
@@ -178,7 +241,7 @@
         `when`(userTracker.userId).thenReturn(guestInfo.id)
         `when`(userTracker.userInfo).thenReturn(guestInfo)
 
-        userSwitcherController.onUserListItemClicked(currentGuestUserRecord)
+        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, null)
         assertNotNull(userSwitcherController.mExitGuestDialog)
         userSwitcherController.mExitGuestDialog
                 .getButton(DialogInterface.BUTTON_POSITIVE).performClick()
@@ -188,6 +251,46 @@
     }
 
     @Test
+    fun testRemoveGuest_removeButtonPressed_dialogDismissed() {
+        val currentGuestUserRecord = UserSwitcherController.UserRecord(
+                guestInfo,
+                picture,
+                true /* guest */,
+                true /* current */,
+                false /* isAddUser */,
+                false /* isRestricted */,
+                true /* isSwitchToEnabled */)
+        `when`(userTracker.userId).thenReturn(guestInfo.id)
+        `when`(userTracker.userInfo).thenReturn(guestInfo)
+
+        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, null)
+        assertNotNull(userSwitcherController.mExitGuestDialog)
+        userSwitcherController.mExitGuestDialog
+                .getButton(DialogInterface.BUTTON_POSITIVE).performClick()
+        testableLooper.processAllMessages()
+        assertFalse(userSwitcherController.mExitGuestDialog.isShowing)
+    }
+
+    @Test
+    fun testRemoveGuest_dialogShowerUsed() {
+        val currentGuestUserRecord = UserSwitcherController.UserRecord(
+                guestInfo,
+                picture,
+                true /* guest */,
+                true /* current */,
+                false /* isAddUser */,
+                false /* isRestricted */,
+                true /* isSwitchToEnabled */)
+        `when`(userTracker.userId).thenReturn(guestInfo.id)
+        `when`(userTracker.userInfo).thenReturn(guestInfo)
+
+        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, dialogShower)
+        assertNotNull(userSwitcherController.mExitGuestDialog)
+        testableLooper.processAllMessages()
+        verify(dialogShower).showDialog(userSwitcherController.mExitGuestDialog)
+    }
+
+    @Test
     fun testRemoveGuest_cancelButtonPressed_isNotLogged() {
         val currentGuestUserRecord = UserSwitcherController.UserRecord(
                 guestInfo,
@@ -200,7 +303,7 @@
         `when`(userTracker.userId).thenReturn(guestId)
         `when`(userTracker.userInfo).thenReturn(guestInfo)
 
-        userSwitcherController.onUserListItemClicked(currentGuestUserRecord)
+        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, null)
         assertNotNull(userSwitcherController.mExitGuestDialog)
         userSwitcherController.mExitGuestDialog
                 .getButton(DialogInterface.BUTTON_NEGATIVE).performClick()
@@ -226,7 +329,7 @@
                 eq(GuestResumeSessionReceiver.SETTING_GUEST_HAS_LOGGED_IN), anyInt(), anyInt()))
                 .thenReturn(1)
 
-        userSwitcherController.onUserListItemClicked(currentGuestUserRecord)
+        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, null)
 
         // Simulate a user switch event
         val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, guestId)
@@ -260,7 +363,7 @@
                 eq(GuestResumeSessionReceiver.SETTING_GUEST_HAS_LOGGED_IN), anyInt(), anyInt()))
                 .thenReturn(1)
 
-        userSwitcherController.onUserListItemClicked(currentGuestUserRecord)
+        userSwitcherController.onUserListItemClicked(currentGuestUserRecord, null)
 
         // Simulate a user switch event
         val intent = Intent(Intent.ACTION_USER_SWITCHED).putExtra(Intent.EXTRA_USER_HANDLE, guestId)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
index 336f2b1..3fe1a9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
@@ -36,6 +36,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.statusbar.policy.ZenModeController.Callback;
+import com.android.systemui.util.settings.FakeSettings;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -70,7 +71,8 @@
                 mContext,
                 Handler.createAsync(Looper.myLooper()),
                 mBroadcastDispatcher,
-                mDumpManager);
+                mDumpManager,
+                new FakeSettings());
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index 766471b..ccb4f67 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -53,6 +53,7 @@
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
+import com.android.systemui.flags.Flags;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.settings.UserTracker;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -114,7 +115,7 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        when(mFeatureFlags.isMonetEnabled()).thenReturn(true);
+        when(mFeatureFlags.isEnabled(Flags.MONET)).thenReturn(true);
         when(mWakefulnessLifecycle.getWakefulness()).thenReturn(WAKEFULNESS_AWAKE);
         when(mDeviceProvisionedController.isCurrentUserSetup()).thenReturn(true);
         mThemeOverlayController = new ThemeOverlayController(null /* context */,
@@ -248,8 +249,9 @@
                 Color.valueOf(Color.BLUE), null);
 
         String jsonString =
-                "{\"android.theme.customization.system_palette\":\"override.package.name\","
-                        + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+                "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+                        + "\"android.theme.customization.system_palette\":\"A16B00\","
+                        + "\"android.theme.customization.accent_color\":\"A16B00\","
                         + "\"android.theme.customization.color_index\":\"2\"}";
 
         when(mSecureSettings.getStringForUser(
@@ -274,14 +276,15 @@
     }
 
     @Test
-    public void onWallpaperColorsChanged_ResetThemeWithDifferentWallpapers() {
+    public void onWallpaperColorsChanged_ResetThemeWithNewHomeWallpapers() {
         // Should ask for a new theme when wallpaper colors change
         WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
                 Color.valueOf(Color.BLUE), null);
 
         String jsonString =
-                "{\"android.theme.customization.system_palette\":\"override.package.name\","
-                        + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+                "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+                        + "\"android.theme.customization.system_palette\":\"A16B00\","
+                        + "\"android.theme.customization.accent_color\":\"A16B00\","
                         + "\"android.theme.customization.color_index\":\"2\"}";
 
         when(mSecureSettings.getStringForUser(
@@ -304,14 +307,15 @@
     }
 
     @Test
-    public void onWallpaperColorsChanged_ResetThemeWithSameWallpaper() {
+    public void onWallpaperColorsChanged_ResetThemeWithNewHomeAndLockWallpaper() {
         // Should ask for a new theme when wallpaper colors change
         WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
                 Color.valueOf(Color.BLUE), null);
 
         String jsonString =
-                "{\"android.theme.customization.system_palette\":\"override.package.name\","
-                        + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+                "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+                        + "\"android.theme.customization.system_palette\":\"A16B00\","
+                        + "\"android.theme.customization.accent_color\":\"A16B00\","
                         + "\"android.theme.customization.color_index\":\"2\"}";
 
         when(mSecureSettings.getStringForUser(
@@ -339,8 +343,9 @@
         WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
                 Color.valueOf(Color.BLUE), null);
         String jsonString =
-                "{\"android.theme.customization.system_palette\":\"override.package.name\","
-                        + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+                "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+                        + "\"android.theme.customization.system_palette\":\"A16B00\","
+                        + "\"android.theme.customization.accent_color\":\"A16B00\","
                         + "\"android.theme.customization.color_index\":\"2\"}";
         when(mSecureSettings.getStringForUser(
                 eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -366,8 +371,9 @@
         WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
                 Color.valueOf(Color.BLUE), null);
         String jsonString =
-                "{\"android.theme.customization.system_palette\":\"override.package.name\","
-                        + "\"android.theme.customization.color_source\":\"lock_wallpaper\","
+                "{\"android.theme.customization.color_source\":\"lock_wallpaper\","
+                        + "\"android.theme.customization.system_palette\":\"A16B00\","
+                        + "\"android.theme.customization.accent_color\":\"A16B00\","
                         + "\"android.theme.customization.color_index\":\"2\"}";
         when(mSecureSettings.getStringForUser(
                 eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
@@ -394,8 +400,9 @@
                 Color.valueOf(Color.BLUE), null);
 
         String jsonString =
-                "{\"android.theme.customization.system_palette\":\"override.package.name\","
-                        + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+                "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+                        + "\"android.theme.customization.system_palette\":\"A16B00\","
+                        + "\"android.theme.customization.accent_color\":\"A16B00\","
                         + "\"android.theme.customization.color_index\":\"2\"}";
 
         when(mSecureSettings.getStringForUser(
@@ -416,6 +423,36 @@
     }
 
     @Test
+    public void onWallpaperColorsChanged_keepThemeWhenFromLatestWallpaperAndSpecifiedColor() {
+        // Shouldn't ask for a new theme when the colors of the last applied wallpaper change
+        // with the same specified system palette one.
+        WallpaperColors mainColors = new WallpaperColors(Color.valueOf(Color.RED),
+                Color.valueOf(0xffa16b00), null);
+
+        String jsonString =
+                "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+                        + "\"android.theme.customization.system_palette\":\"A16B00\","
+                        + "\"android.theme.customization.accent_color\":\"A16B00\","
+                        + "\"android.theme.customization.color_index\":\"2\"}";
+
+        when(mSecureSettings.getStringForUser(
+                eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), anyInt()))
+                .thenReturn(jsonString);
+        when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_LOCK)).thenReturn(1);
+        // SYSTEM wallpaper is the last applied one
+        when(mWallpaperManager.getWallpaperId(WallpaperManager.FLAG_SYSTEM)).thenReturn(2);
+
+        mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);
+
+        ArgumentCaptor<String> updatedSetting = ArgumentCaptor.forClass(String.class);
+        verify(mSecureSettings, never()).putString(
+                eq(Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES), updatedSetting.capture());
+
+        // Apply overlay by existing theme from secure setting
+        verify(mThemeOverlayApplier).applyCurrentUserOverlays(any(), any(), anyInt(), any());
+    }
+
+    @Test
     public void onWallpaperColorsChanged_keepThemeIfNotLatestWallpaper() {
         // Shouldn't ask for a new theme when the colors of the wallpaper that is not the last
         // applied one change
@@ -423,8 +460,9 @@
                 Color.valueOf(Color.BLUE), null);
 
         String jsonString =
-                "{\"android.theme.customization.system_palette\":\"override.package.name\","
-                        + "\"android.theme.customization.color_source\":\"home_wallpaper\","
+                "{\"android.theme.customization.color_source\":\"home_wallpaper\","
+                        + "\"android.theme.customization.system_palette\":\"A16B00\","
+                        + "\"android.theme.customization.accent_color\":\"A16B00\","
                         + "\"android.theme.customization.color_index\":\"2\"}";
 
         when(mSecureSettings.getStringForUser(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index c900ad5..a8e92f5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -76,7 +76,6 @@
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -85,6 +84,7 @@
 import com.android.systemui.statusbar.NotificationRemoveInterceptor;
 import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationFilter;
@@ -221,7 +221,7 @@
     @Mock
     private NotifPipeline mNotifPipeline;
     @Mock
-    private FeatureFlags mFeatureFlagsOldPipeline;
+    private NotifPipelineFlags mNotifPipelineFlags;
     @Mock
     private DumpManager mDumpManager;
     @Mock
@@ -326,7 +326,7 @@
                         mock(Handler.class)
                 );
 
-        when(mFeatureFlagsOldPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
+        when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(false);
         when(mShellTaskOrganizer.getExecutor()).thenReturn(syncExecutor);
         mBubbleController = new TestableBubbleController(
                 mContext,
@@ -365,7 +365,7 @@
                 mNotificationEntryManager,
                 mNotifPipeline,
                 mSysUiState,
-                mFeatureFlagsOldPipeline,
+                mNotifPipelineFlags,
                 mDumpManager,
                 syncExecutor);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
index 5ab2113..8027390 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/NewNotifPipelineBubblesTest.java
@@ -64,7 +64,6 @@
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.model.SysUiState;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -72,6 +71,7 @@
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.RankingBuilder;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.notification.NotifPipelineFlags;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationFilter;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
@@ -199,7 +199,7 @@
     @Mock
     private NotifPipeline mNotifPipeline;
     @Mock
-    private FeatureFlags mFeatureFlagsNewPipeline;
+    private NotifPipelineFlags mNotifPipelineFlags;
     @Mock
     private DumpManager mDumpManager;
     @Mock
@@ -291,7 +291,7 @@
                         mock(HeadsUpManager.class),
                         mock(Handler.class)
                 );
-        when(mFeatureFlagsNewPipeline.isNewNotifPipelineRenderingEnabled()).thenReturn(true);
+        when(mNotifPipelineFlags.isNewPipelineEnabled()).thenReturn(true);
         when(mShellTaskOrganizer.getExecutor()).thenReturn(syncExecutor);
         mBubbleController = new TestableBubbleController(
                 mContext,
@@ -330,7 +330,7 @@
                 mNotificationEntryManager,
                 mNotifPipeline,
                 mSysUiState,
-                mFeatureFlagsNewPipeline,
+                mNotifPipelineFlags,
                 mDumpManager,
                 syncExecutor);
         mBubblesManager.addNotifCallback(mNotifCallback);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
index 8480702..ae7afce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/WMShellTest.java
@@ -41,6 +41,7 @@
 import com.android.wm.shell.onehanded.OneHandedEventCallback;
 import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
 import com.android.wm.shell.pip.Pip;
+import com.android.wm.shell.sizecompatui.SizeCompatUI;
 import com.android.wm.shell.splitscreen.SplitScreen;
 
 import org.junit.Before;
@@ -76,6 +77,7 @@
     @Mock WakefulnessLifecycle mWakefulnessLifecycle;
     @Mock ProtoTracer mProtoTracer;
     @Mock ShellCommandHandler mShellCommandHandler;
+    @Mock SizeCompatUI mSizeCompatUI;
     @Mock ShellExecutor mSysUiMainExecutor;
 
     @Before
@@ -84,10 +86,10 @@
 
         mWMShell = new WMShell(mContext, Optional.of(mPip), Optional.of(mLegacySplitScreen),
                 Optional.of(mSplitScreen), Optional.of(mOneHanded), Optional.of(mHideDisplayCutout),
-                Optional.of(mShellCommandHandler), mCommandQueue, mConfigurationController,
-                mKeyguardUpdateMonitor, mNavigationModeController,
-                mScreenLifecycle, mSysUiState, mProtoTracer, mWakefulnessLifecycle,
-                mSysUiMainExecutor);
+                Optional.of(mShellCommandHandler), Optional.of(mSizeCompatUI),
+                mCommandQueue, mConfigurationController, mKeyguardUpdateMonitor,
+                mNavigationModeController, mScreenLifecycle, mSysUiState, mProtoTracer,
+                mWakefulnessLifecycle, mSysUiMainExecutor);
     }
 
     @Test
@@ -129,4 +131,11 @@
         verify(mConfigurationController).addCallback(
                 any(ConfigurationController.ConfigurationListener.class));
     }
+
+    @Test
+    public void initSizeCompatUI_registersCallbacks() {
+        mWMShell.initSizeCompatUi(mSizeCompatUI);
+
+        verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class));
+    }
 }
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index 928892c..69641e6 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -31,7 +31,6 @@
 	NavigationBarModeGesturalOverlayNarrowBack \
 	NavigationBarModeGesturalOverlayWideBack \
 	NavigationBarModeGesturalOverlayExtraWideBack \
-        OneHandedModeGesturalOverlay \
 	preinstalled-packages-platform-overlays.xml
 
 include $(BUILD_PHONY_PACKAGE)
diff --git a/packages/overlays/OneHandedModeGesturalOverlay/AndroidManifest.xml b/packages/overlays/OneHandedModeGesturalOverlay/AndroidManifest.xml
deleted file mode 100644
index e4867df..0000000
--- a/packages/overlays/OneHandedModeGesturalOverlay/AndroidManifest.xml
+++ /dev/null
@@ -1,28 +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.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.internal.systemui.onehanded.gestural"
-        android:versionCode="1"
-        android:versionName="1.0">
-    <overlay android:targetPackage="android"
-        android:category="com.android.internal.one_handed_mode"
-        android:priority="2"/>
-    <!-- To override dimen in NavigationBarModeGesturalOverlay, priority should be higher -->
-
-    <application android:label="@string/one_handed_mode_title" android:hasCode="false"/>
-</manifest>
diff --git a/packages/overlays/OneHandedModeGesturalOverlay/res/values/strings.xml b/packages/overlays/OneHandedModeGesturalOverlay/res/values/strings.xml
deleted file mode 100644
index 9e8c779..0000000
--- a/packages/overlays/OneHandedModeGesturalOverlay/res/values/strings.xml
+++ /dev/null
@@ -1,22 +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.
- */
--->
-<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <!-- Name of overlay [CHAR LIMIT=64] -->
-    <string name="one_handed_mode_title" translatable="false">One Handed Mode</string>
-</resources>
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 67bb726..f1599e4 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -39,6 +39,7 @@
 import android.accessibilityservice.AccessibilityTrace;
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.accessibilityservice.IAccessibilityServiceConnection;
+import android.accessibilityservice.MagnificationConfig;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.PendingIntent;
@@ -1101,8 +1102,12 @@
             try {
                 MagnificationProcessor magnificationProcessor =
                         mSystemSupport.getMagnificationProcessor();
-                return magnificationProcessor
-                        .setScaleAndCenter(displayId, scale, centerX, centerY, animate, mId);
+                final MagnificationConfig config = new MagnificationConfig.Builder()
+                        .setScale(scale)
+                        .setCenterX(centerX)
+                        .setCenterY(centerY).build();
+                return magnificationProcessor.setMagnificationConfig(displayId, config, animate,
+                        mId);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 0e39327..52a6dc1 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2382,6 +2382,7 @@
         somethingChanged |= readTouchExplorationGrantedAccessibilityServicesLocked(userState);
         somethingChanged |= readTouchExplorationEnabledSettingLocked(userState);
         somethingChanged |= readHighTextContrastEnabledSettingLocked(userState);
+        somethingChanged |= readAudioDescriptionEnabledSettingLocked(userState);
         somethingChanged |= readMagnificationEnabledSettingsLocked(userState);
         somethingChanged |= readAutoclickEnabledSettingLocked(userState);
         somethingChanged |= readAccessibilityShortcutKeySettingLocked(userState);
@@ -2454,6 +2455,19 @@
         return false;
     }
 
+    private boolean readAudioDescriptionEnabledSettingLocked(AccessibilityUserState userState) {
+        final boolean audioDescriptionByDefaultEnabled = Settings.Secure.getIntForUser(
+                mContext.getContentResolver(),
+                Settings.Secure.ENABLED_ACCESSIBILITY_AUDIO_DESCRIPTION_BY_DEFAULT, 0,
+                userState.mUserId) == 1;
+        if (audioDescriptionByDefaultEnabled
+                    != userState.isAudioDescriptionByDefaultEnabledLocked()) {
+            userState.setAudioDescriptionByDefaultEnabledLocked(audioDescriptionByDefaultEnabled);
+            return true;
+        }
+        return false;
+    }
+
     private void updateTouchExplorationLocked(AccessibilityUserState userState) {
         boolean touchExplorationEnabled = mUiAutomationManager.isTouchExplorationEnabledLocked();
         boolean serviceHandlesDoubleTapEnabled = false;
@@ -3418,6 +3432,23 @@
         }
     }
 
+    /**
+     * Gets the status of the audio description preference.
+     * @return {@code true} if the audio description is enabled, {@code false} otherwise.
+     */
+    @Override
+    public boolean isAudioDescriptionByDefaultEnabled() {
+        if (mTraceManager.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_MANAGER)) {
+            mTraceManager.logTrace(LOG_TAG + ".isAudioDescriptionByDefaultEnabled",
+                    FLAGS_ACCESSIBILITY_MANAGER);
+        }
+        synchronized (mLock) {
+            final AccessibilityUserState userState = getCurrentUserStateLocked();
+
+            return userState.isAudioDescriptionByDefaultEnabledLocked();
+        }
+    }
+
     @Override
     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
@@ -3528,9 +3559,8 @@
 
             mConnectionId = service.mId;
 
-            mClient = AccessibilityInteractionClient.getInstance(/* initializeCache= */false,
-                    mContext);
-            mClient.addConnection(mConnectionId, service);
+            mClient = AccessibilityInteractionClient.getInstance(mContext);
+            mClient.addConnection(mConnectionId, service, /*initializeCache=*/false);
 
             //TODO: (multi-display) We need to support multiple displays.
             DisplayManager displayManager = (DisplayManager)
@@ -3576,31 +3606,36 @@
             }
 
             synchronized (mLock) {
-                Rect boundsInScreen = mTempRect;
-                focus.getBoundsInScreen(boundsInScreen);
+                Rect boundsInScreenBeforeMagnification = mTempRect;
 
-                // Apply magnification if needed.
+                focus.getBoundsInScreen(boundsInScreenBeforeMagnification);
+                final Point nodeCenter = new Point(boundsInScreenBeforeMagnification.centerX(),
+                        boundsInScreenBeforeMagnification.centerY());
+
+                // Invert magnification if needed.
                 MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
                 if (spec != null && !spec.isNop()) {
-                    boundsInScreen.offset((int) -spec.offsetX, (int) -spec.offsetY);
-                    boundsInScreen.scale(1 / spec.scale);
+                    boundsInScreenBeforeMagnification.offset((int) -spec.offsetX,
+                            (int) -spec.offsetY);
+                    boundsInScreenBeforeMagnification.scale(1 / spec.scale);
                 }
 
-                // Clip to the window bounds.
+                //Clip to the window bounds.
                 Rect windowBounds = mTempRect1;
                 getWindowBounds(focus.getWindowId(), windowBounds);
-                if (!boundsInScreen.intersect(windowBounds)) {
+                if (!boundsInScreenBeforeMagnification.intersect(windowBounds)) {
                     return false;
                 }
 
-                // Clip to the screen bounds.
+                //Clip to the screen bounds.
                 Point screenSize = mTempPoint;
                 mDefaultDisplay.getRealSize(screenSize);
-                if (!boundsInScreen.intersect(0, 0, screenSize.x, screenSize.y)) {
+                if (!boundsInScreenBeforeMagnification.intersect(0, 0, screenSize.x,
+                        screenSize.y)) {
                     return false;
                 }
 
-                outPoint.set(boundsInScreen.centerX(), boundsInScreen.centerY());
+                outPoint.set(nodeCenter.x, nodeCenter.y);
             }
 
             return true;
@@ -3704,6 +3739,7 @@
                 }
                 updateMagnificationLocked(userState);
                 updateWindowsForAccessibilityCallbackLocked(userState);
+                notifyClearAccessibilityCacheLocked();
             }
         }
 
@@ -3800,6 +3836,9 @@
         private final Uri mHighTextContrastUri = Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED);
 
+        private final Uri mAudioDescriptionByDefaultUri = Settings.Secure.getUriFor(
+                Settings.Secure.ENABLED_ACCESSIBILITY_AUDIO_DESCRIPTION_BY_DEFAULT);
+
         private final Uri mAccessibilitySoftKeyboardModeUri = Settings.Secure.getUriFor(
                 Settings.Secure.ACCESSIBILITY_SOFT_KEYBOARD_MODE);
 
@@ -3846,6 +3885,8 @@
             contentResolver.registerContentObserver(
                     mHighTextContrastUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
+                    mAudioDescriptionByDefaultUri, false, this, UserHandle.USER_ALL);
+            contentResolver.registerContentObserver(
                     mAccessibilitySoftKeyboardModeUri, false, this, UserHandle.USER_ALL);
             contentResolver.registerContentObserver(
                     mShowImeWithHardKeyboardUri, false, this, UserHandle.USER_ALL);
@@ -3899,6 +3940,10 @@
                     if (readHighTextContrastEnabledSettingLocked(userState)) {
                         onUserStateChangedLocked(userState);
                     }
+                } else if (mAudioDescriptionByDefaultUri.equals(uri)) {
+                    if (readAudioDescriptionEnabledSettingLocked(userState)) {
+                        onUserStateChangedLocked(userState);
+                    }
                 } else if (mAccessibilitySoftKeyboardModeUri.equals(uri)
                         || mShowImeWithHardKeyboardUri.equals(uri)) {
                     userState.reconcileSoftKeyboardModeWithSettingsLocked();
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
index e9f5870..bcb3413 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java
@@ -406,7 +406,7 @@
     @Override
     public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) {
         synchronized (mLock) {
-            if (mSecurityPolicy.canPerformGestures(this)) {
+            if (mServiceInterface != null && mSecurityPolicy.canPerformGestures(this)) {
                 MotionEventInjector motionEventInjector =
                         mSystemSupport.getMotionEventInjectorForDisplayLocked(displayId);
                 if (wmTracingEnabled()) {
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index 8c3ca34..9324e3e 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -105,6 +105,7 @@
     private String mTargetAssignedToAccessibilityButton;
 
     private boolean mBindInstantServiceAllowed;
+    private boolean mIsAudioDescriptionByDefaultRequested;
     private boolean mIsAutoclickEnabled;
     private boolean mIsDisplayMagnificationEnabled;
     private boolean mIsFilterKeyEventsEnabled;
@@ -411,6 +412,10 @@
         if (mIsTextHighContrastEnabled) {
             clientState |= AccessibilityManager.STATE_FLAG_HIGH_TEXT_CONTRAST_ENABLED;
         }
+        if (mIsAudioDescriptionByDefaultRequested) {
+            clientState |=
+                    AccessibilityManager.STATE_FLAG_AUDIO_DESCRIPTION_BY_DEFAULT_ENABLED;
+        }
 
         clientState |= traceClientState;
 
@@ -506,6 +511,8 @@
         pw.append(", magnificationModes=").append(String.valueOf(mMagnificationModes));
         pw.append(", magnificationCapabilities=")
                 .append(String.valueOf(mMagnificationCapabilities));
+        pw.append(", audioDescriptionByDefaultEnabled=")
+                .append(String.valueOf(mIsAudioDescriptionByDefaultRequested));
         pw.append("}");
         pw.println();
         pw.append("     shortcut key:{");
@@ -824,6 +831,14 @@
         mIsTextHighContrastEnabled = enabled;
     }
 
+    public boolean isAudioDescriptionByDefaultEnabledLocked() {
+        return mIsAudioDescriptionByDefaultRequested;
+    }
+
+    public void setAudioDescriptionByDefaultEnabledLocked(boolean enabled) {
+        mIsAudioDescriptionByDefaultRequested = enabled;
+    }
+
     public boolean isTouchExplorationEnabledLocked() {
         return mIsTouchExplorationEnabled;
     }
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 946d22e4..86777a2 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -537,6 +537,8 @@
         // touch, we figure out what to do. If were waiting
         // we resent the delayed callback and wait again.
         mSendHoverEnterAndMoveDelayed.cancel();
+        // clear any hover events that might have been queued and never sent.
+        mSendHoverEnterAndMoveDelayed.clear();
         mSendHoverExitDelayed.cancel();
         // If a touch exploration gesture is in progress send events for its end.
         if (mState.isTouchExploring()) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
index 6473bf5..42a81e1 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -20,7 +20,9 @@
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
 import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
+import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;
 
+import android.accessibilityservice.MagnificationConfig;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
@@ -74,6 +76,7 @@
     private final PointF mTempPoint = new PointF();
     private final Object mLock;
     private final Context mContext;
+    @GuardedBy("mLock")
     private final SparseArray<DisableMagnificationCallback>
             mMagnificationEndRunnableSparseArray = new SparseArray();
 
@@ -84,6 +87,8 @@
 
     @GuardedBy("mLock")
     private int mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
+    @GuardedBy("mLock")
+    private int mLastActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
     // Track the active user to reset the magnification and get the associated user settings.
     private @UserIdInt int mUserId = UserHandle.USER_SYSTEM;
     @GuardedBy("mLock")
@@ -206,7 +211,7 @@
         final float scale = mScaleProvider.getScale(displayId);
         final DisableMagnificationCallback animationEndCallback =
                 new DisableMagnificationCallback(transitionCallBack, displayId, targetMode,
-                        scale, magnificationCenter);
+                        scale, magnificationCenter, true);
         if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
             screenMagnificationController.reset(displayId, animationEndCallback);
         } else {
@@ -216,6 +221,77 @@
         setDisableMagnificationCallbackLocked(displayId, animationEndCallback);
     }
 
+    /**
+     * Transitions to the targeting magnification config mode with current center of the
+     * magnification mode if it is available. It disables the current magnifier immediately then
+     * transitions to the targeting magnifier.
+     *
+     * @param displayId  The logical display id
+     * @param config The targeting magnification config
+     * @param animate    {@code true} to animate the transition, {@code false}
+     *                   to transition immediately
+     */
+    public void transitionMagnificationConfigMode(int displayId, MagnificationConfig config,
+            boolean animate) {
+        synchronized (mLock) {
+            final int targetMode = config.getMode();
+            final PointF currentBoundsCenter = getCurrentMagnificationBoundsCenterLocked(displayId,
+                    targetMode);
+            final PointF magnificationCenter = new PointF(config.getCenterX(), config.getCenterY());
+            if (currentBoundsCenter != null) {
+                final float centerX = Float.isNaN(config.getCenterX())
+                        ? currentBoundsCenter.x
+                        : config.getCenterX();
+                final float centerY = Float.isNaN(config.getCenterY())
+                        ? currentBoundsCenter.y
+                        : config.getCenterY();
+                magnificationCenter.set(centerX, centerY);
+            }
+
+            final DisableMagnificationCallback animationCallback =
+                    getDisableMagnificationEndRunnableLocked(displayId);
+            if (animationCallback != null) {
+                Slog.w(TAG, "Discard previous animation request");
+                animationCallback.setExpiredAndRemoveFromListLocked();
+            }
+
+            final FullScreenMagnificationController screenMagnificationController =
+                    getFullScreenMagnificationController();
+            final WindowMagnificationManager windowMagnificationMgr = getWindowMagnificationMgr();
+            final float scale = mScaleProvider.getScale(displayId);
+            if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW) {
+                screenMagnificationController.reset(displayId, false);
+                windowMagnificationMgr.enableWindowMagnification(displayId,
+                        scale, magnificationCenter.x, magnificationCenter.y,
+                        animate ? STUB_ANIMATION_CALLBACK : null);
+            } else if (targetMode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) {
+                windowMagnificationMgr.disableWindowMagnification(displayId, false, null);
+                if (!screenMagnificationController.isRegistered(displayId)) {
+                    screenMagnificationController.register(displayId);
+                }
+                screenMagnificationController.setScaleAndCenter(displayId, scale,
+                        magnificationCenter.x, magnificationCenter.y, animate,
+                        AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
+            }
+        }
+    }
+
+    /**
+     * Return {@code true} if disable magnification animation callback of the display is running.
+     *
+     * @param displayId The logical display id
+     */
+    public boolean hasDisableMagnificationCallback(int displayId) {
+        synchronized (mLock) {
+            final DisableMagnificationCallback animationCallback =
+                    getDisableMagnificationEndRunnableLocked(displayId);
+            if (animationCallback != null) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     public void onRequestMagnificationSpec(int displayId, int serviceId) {
         final WindowMagnificationManager windowMagnificationManager;
@@ -239,6 +315,7 @@
 
             synchronized (mLock) {
                 mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
+                mLastActivatedMode = mActivatedMode;
             }
             logMagnificationModeWithImeOnIfNeeded();
             disableFullScreenMagnificationIfNeeded(displayId);
@@ -264,7 +341,8 @@
         // Internal request may be for transition, so we just need to check external request.
         final boolean isMagnifyByExternalRequest =
                 fullScreenMagnificationController.getIdOfLastServiceToMagnify(displayId) > 0;
-        if (isMagnifyByExternalRequest) {
+        if (isMagnifyByExternalRequest || isActivated(displayId,
+                ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN)) {
             fullScreenMagnificationController.reset(displayId, false);
         }
     }
@@ -276,8 +354,10 @@
 
             synchronized (mLock) {
                 mActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+                mLastActivatedMode = mActivatedMode;
             }
             logMagnificationModeWithImeOnIfNeeded();
+            disableWindowMagnificationIfNeeded(displayId);
         } else {
             logMagnificationUsageState(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
                     SystemClock.uptimeMillis() - mFullScreenModeEnabledTime);
@@ -289,6 +369,14 @@
         updateMagnificationButton(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
     }
 
+    private void disableWindowMagnificationIfNeeded(int displayId) {
+        final WindowMagnificationManager windowMagnificationManager =
+                getWindowMagnificationMgr();
+        if (isActivated(displayId, ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)) {
+            windowMagnificationManager.disableWindowMagnification(displayId, false);
+        }
+    }
+
     @Override
     public void onImeWindowVisibilityChanged(boolean shown) {
         synchronized (mLock) {
@@ -298,6 +386,16 @@
     }
 
     /**
+     * Returns the last activated magnification mode. If there is no activated magnifier before, it
+     * returns fullscreen mode by default.
+     */
+    public int getLastActivatedMode() {
+        synchronized (mLock) {
+            return mLastActivatedMode;
+        }
+    }
+
+    /**
      * Wrapper method of logging the magnification activated mode and its duration of the usage
      * when the magnification is disabled.
      *
@@ -336,6 +434,7 @@
         synchronized (mLock) {
             fullMagnificationController = mFullScreenMagnificationController;
             windowMagnificationManager = mWindowMagnificationMgr;
+            mLastActivatedMode = ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
         }
 
         mScaleProvider.onUserChanged(userId);
@@ -462,7 +561,15 @@
         return mTempPoint;
     }
 
-    private boolean isActivated(int displayId, int mode) {
+    /**
+     * Return {@code true} if the specified magnification mode on the given display is activated
+     * or not.
+     *
+     * @param displayId The logical displayId.
+     * @param mode It's either ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN or
+     * ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW.
+     */
+    public boolean isActivated(int displayId, int mode) {
         boolean isActivated = false;
         if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) {
             synchronized (mLock) {
@@ -495,15 +602,17 @@
         private final int mCurrentMode;
         private final float mCurrentScale;
         private final PointF mCurrentCenter = new PointF();
+        private final boolean mAnimate;
 
-        DisableMagnificationCallback(TransitionCallBack transitionCallBack,
-                int displayId, int targetMode, float scale, PointF currentCenter) {
+        DisableMagnificationCallback(@Nullable TransitionCallBack transitionCallBack,
+                int displayId, int targetMode, float scale, PointF currentCenter, boolean animate) {
             mTransitionCallBack = transitionCallBack;
             mDisplayId = displayId;
             mTargetMode = targetMode;
             mCurrentMode = mTargetMode ^ ACCESSIBILITY_MAGNIFICATION_MODE_ALL;
             mCurrentScale = scale;
             mCurrentCenter.set(currentCenter);
+            mAnimate = animate;
         }
 
         @Override
@@ -521,7 +630,9 @@
                     applyMagnificationModeLocked(mTargetMode);
                 }
                 updateMagnificationButton(mDisplayId, mTargetMode);
-                mTransitionCallBack.onResult(mDisplayId, success);
+                if (mTransitionCallBack != null) {
+                    mTransitionCallBack.onResult(mDisplayId, success);
+                }
             }
         }
 
@@ -546,7 +657,9 @@
                 setExpiredAndRemoveFromListLocked();
                 applyMagnificationModeLocked(mCurrentMode);
                 updateMagnificationButton(mDisplayId, mCurrentMode);
-                mTransitionCallBack.onResult(mDisplayId, true);
+                if (mTransitionCallBack != null) {
+                    mTransitionCallBack.onResult(mDisplayId, true);
+                }
             }
         }
 
@@ -557,9 +670,13 @@
 
         private void applyMagnificationModeLocked(int mode) {
             if (mode == ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN) {
-                getFullScreenMagnificationController().setScaleAndCenter(mDisplayId,
-                        mCurrentScale, mCurrentCenter.x,
-                        mCurrentCenter.y, true,
+                final FullScreenMagnificationController fullScreenMagnificationController =
+                        getFullScreenMagnificationController();
+                if (!fullScreenMagnificationController.isRegistered(mDisplayId)) {
+                    fullScreenMagnificationController.register(mDisplayId);
+                }
+                fullScreenMagnificationController.setScaleAndCenter(mDisplayId, mCurrentScale,
+                        mCurrentCenter.x, mCurrentCenter.y, mAnimate,
                         AccessibilityManagerService.MAGNIFICATION_GESTURE_HANDLER_ID);
             } else {
                 getWindowMagnificationMgr().enableWindowMagnification(mDisplayId,
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
index efc6d51..dda1c4f 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationProcessor.java
@@ -16,6 +16,13 @@
 
 package com.android.server.accessibility.magnification;
 
+import static android.accessibilityservice.MagnificationConfig.DEFAULT_MODE;
+import static android.accessibilityservice.MagnificationConfig.FULLSCREEN_MODE;
+import static android.accessibilityservice.MagnificationConfig.WINDOW_MODE;
+import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
+import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
+
+import android.accessibilityservice.MagnificationConfig;
 import android.annotation.NonNull;
 import android.graphics.Region;
 
@@ -23,6 +30,22 @@
  * Processor class for AccessibilityService connection to control magnification on the specified
  * display. This wraps the function of magnification controller.
  *
+ * <p>
+ * If the magnification config uses {@link DEFAULT_MODE}. This processor will control the current
+ * activated magnifier on the display. If there is no magnifier activated, it controls
+ * full-screen magnifier by default.
+ * </p>
+ *
+ * <p>
+ * If the magnification config uses {@link FULLSCREEN_MODE}. This processor will control
+ * full-screen magnifier on the display.
+ * </p>
+ *
+ * <p>
+ * If the magnification config uses {@link WINDOW_MODE}. This processor will control
+ * the activated window magnifier on the display.
+ * </p>
+ *
  * @see MagnificationController
  * @see FullScreenMagnificationController
  */
@@ -35,53 +58,185 @@
     }
 
     /**
-     * {@link FullScreenMagnificationController#getScale(int)}
+     * Gets the magnification config of the display.
+     *
+     * @param displayId The logical display id
+     * @return the magnification config
+     */
+    public @NonNull MagnificationConfig getMagnificationConfig(int displayId) {
+        final int mode = getControllingMode(displayId);
+        MagnificationConfig.Builder builder = new MagnificationConfig.Builder();
+        if (mode == FULLSCREEN_MODE) {
+            final FullScreenMagnificationController fullScreenMagnificationController =
+                    mController.getFullScreenMagnificationController();
+            builder.setMode(mode)
+                    .setScale(fullScreenMagnificationController.getScale(displayId))
+                    .setCenterX(fullScreenMagnificationController.getCenterX(displayId))
+                    .setCenterY(fullScreenMagnificationController.getCenterY(displayId));
+        } else if (mode == WINDOW_MODE) {
+            final WindowMagnificationManager windowMagnificationManager =
+                    mController.getWindowMagnificationMgr();
+            builder.setMode(mode)
+                    .setScale(windowMagnificationManager.getScale(displayId))
+                    .setCenterX(windowMagnificationManager.getCenterX(displayId))
+                    .setCenterY(windowMagnificationManager.getCenterY(displayId));
+        }
+        return builder.build();
+    }
+
+    /**
+     * Sets the magnification config of the display. If animation is disabled, the transition
+     * is immediate.
+     *
+     * @param displayId The logical display id
+     * @param config    The magnification config
+     * @param animate   {@code true} to animate from the current config or
+     *                  {@code false} to set the config immediately
+     * @param id        The ID of the service requesting the change
+     * @return {@code true} if the magnification spec changed, {@code false} if the spec did not
+     * change
+     */
+    public boolean setMagnificationConfig(int displayId, @NonNull MagnificationConfig config,
+            boolean animate, int id) {
+        if (transitionModeIfNeeded(displayId, config, animate)) {
+            return true;
+        }
+
+        int configMode = config.getMode();
+        if (configMode == DEFAULT_MODE) {
+            configMode = getControllingMode(displayId);
+        }
+        if (configMode == FULLSCREEN_MODE) {
+            return setScaleAndCenterForFullScreenMagnification(displayId, config.getScale(),
+                    config.getCenterX(), config.getCenterY(),
+                    animate, id);
+        } else if (configMode == WINDOW_MODE) {
+            return mController.getWindowMagnificationMgr().enableWindowMagnification(displayId,
+                    config.getScale(), config.getCenterX(), config.getCenterY());
+        }
+        return false;
+    }
+
+    /**
+     * Returns {@code true} if transition magnification mode needed. And it is no need to transition
+     * mode when the controlling mode is unchanged or the controlling magnifier is not activated.
+     */
+    private boolean transitionModeIfNeeded(int displayId, MagnificationConfig config,
+            boolean animate) {
+        int currentMode = getControllingMode(displayId);
+        if (currentMode == config.getMode()
+                || !mController.hasDisableMagnificationCallback(displayId)) {
+            return false;
+        }
+        mController.transitionMagnificationConfigMode(displayId, config, animate);
+        return true;
+    }
+
+    /**
+     * Returns the magnification scale. If an animation is in progress,
+     * this reflects the end state of the animation.
+     *
+     * @param displayId The logical display id.
+     * @return the scale
      */
     public float getScale(int displayId) {
-        return mController.getFullScreenMagnificationController().getScale(displayId);
+        int mode = getControllingMode(displayId);
+        if (mode == FULLSCREEN_MODE) {
+            return mController.getFullScreenMagnificationController().getScale(displayId);
+        } else if (mode == WINDOW_MODE) {
+            return mController.getWindowMagnificationMgr().getScale(displayId);
+        }
+        return 0;
     }
 
     /**
-     * {@link FullScreenMagnificationController#getCenterX(int)}
+     * Returns the magnification center in X coordinate of the controlling magnification mode.
+     * If the service can control magnification but fullscreen magnifier is not registered, it will
+     * register the magnifier for this call then unregister the magnifier finally to make the
+     * magnification center correct.
+     *
+     * @param displayId The logical display id
+     * @param canControlMagnification Whether the service can control magnification
+     * @return the X coordinate
      */
     public float getCenterX(int displayId, boolean canControlMagnification) {
-        boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
-                canControlMagnification);
-        try {
-            return mController.getFullScreenMagnificationController().getCenterX(displayId);
-        } finally {
-            if (registeredJustForThisCall) {
-                unregister(displayId);
+        int mode = getControllingMode(displayId);
+        if (mode == FULLSCREEN_MODE) {
+            boolean registeredJustForThisCall = registerDisplayMagnificationIfNeeded(displayId,
+                    canControlMagnification);
+            try {
+                return mController.getFullScreenMagnificationController().getCenterX(displayId);
+            } finally {
+                if (registeredJustForThisCall) {
+                    unregister(displayId);
+                }
             }
+        } else if (mode == WINDOW_MODE) {
+            return mController.getWindowMagnificationMgr().getCenterX(displayId);
         }
+        return 0;
     }
 
     /**
-     * {@link FullScreenMagnificationController#getCenterY(int)}
+     * Returns the magnification center in Y coordinate of the controlling magnification mode.
+     * If the service can control magnification but fullscreen magnifier is not registered, it will
+     * register the magnifier for this call then unregister the magnifier finally to make the
+     * magnification center correct.
+     *
+     * @param displayId The logical display id
+     * @param canControlMagnification Whether the service can control magnification
+     * @return the Y coordinate
      */
     public float getCenterY(int displayId, boolean canControlMagnification) {
-        boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
-                canControlMagnification);
-        try {
-            return mController.getFullScreenMagnificationController().getCenterY(displayId);
-        } finally {
-            if (registeredJustForThisCall) {
-                unregister(displayId);
+        int mode = getControllingMode(displayId);
+        if (mode == FULLSCREEN_MODE) {
+            boolean registeredJustForThisCall = registerDisplayMagnificationIfNeeded(displayId,
+                    canControlMagnification);
+            try {
+                return mController.getFullScreenMagnificationController().getCenterY(displayId);
+            } finally {
+                if (registeredJustForThisCall) {
+                    unregister(displayId);
+                }
             }
+        } else if (mode == WINDOW_MODE) {
+            return mController.getWindowMagnificationMgr().getCenterY(displayId);
         }
+        return 0;
     }
 
     /**
-     * {@link FullScreenMagnificationController#getMagnificationRegion(int, Region)}
+     * Return the magnification bounds of the current controlling magnification on the given
+     * display. If the magnifier is not enabled, it returns an empty region.
+     * If the service can control magnification but fullscreen magnifier is not registered, it will
+     * register the magnifier for this call then unregister the magnifier finally to make
+     * the magnification region correct.
+     *
+     * @param displayId The logical display id
+     * @param outRegion the region to populate
+     * @param canControlMagnification Whether the service can control magnification
+     * @return outRegion the magnification bounds of full-screen magnifier or the magnification
+     * source bounds of window magnifier
      */
     public Region getMagnificationRegion(int displayId, @NonNull Region outRegion,
             boolean canControlMagnification) {
-        boolean registeredJustForThisCall = registerMagnificationIfNeeded(displayId,
+        int mode = getControllingMode(displayId);
+        if (mode == FULLSCREEN_MODE) {
+            getFullscreenMagnificationRegion(displayId, outRegion, canControlMagnification);
+        } else if (mode == WINDOW_MODE) {
+            mController.getWindowMagnificationMgr().getMagnificationSourceBounds(displayId,
+                    outRegion);
+        }
+        return outRegion;
+    }
+
+    private void getFullscreenMagnificationRegion(int displayId, @NonNull Region outRegion,
+            boolean canControlMagnification) {
+        boolean registeredJustForThisCall = registerDisplayMagnificationIfNeeded(displayId,
                 canControlMagnification);
         try {
             mController.getFullScreenMagnificationController().getMagnificationRegion(displayId,
                     outRegion);
-            return outRegion;
         } finally {
             if (registeredJustForThisCall) {
                 unregister(displayId);
@@ -89,67 +244,105 @@
         }
     }
 
-    /**
-     * {@link FullScreenMagnificationController#setScaleAndCenter(int, float, float, float, boolean,
-     * int)}
-     */
-    public boolean setScaleAndCenter(int displayId, float scale, float centerX, float centerY,
+    private boolean setScaleAndCenterForFullScreenMagnification(int displayId, float scale,
+            float centerX, float centerY,
             boolean animate, int id) {
         if (!isRegistered(displayId)) {
             register(displayId);
         }
-        return mController.getFullScreenMagnificationController().setScaleAndCenter(displayId,
+        return mController.getFullScreenMagnificationController().setScaleAndCenter(
+                displayId,
                 scale,
                 centerX, centerY, animate, id);
     }
 
     /**
-     * {@link FullScreenMagnificationController#reset(int, boolean)}
+     * Resets the magnification on the given display. The reset mode could be full-screen or
+     * window if it is activated.
+     *
+     * @param displayId The logical display id.
+     * @param animate   {@code true} to animate the transition, {@code false}
+     *                  to transition immediately
+     * @return {@code true} if the magnification spec changed, {@code false} if
+     * the spec did not change
      */
     public boolean reset(int displayId, boolean animate) {
-        return mController.getFullScreenMagnificationController().reset(displayId, animate);
+        int mode = getControllingMode(displayId);
+        if (mode == FULLSCREEN_MODE) {
+            return mController.getFullScreenMagnificationController().reset(displayId, animate);
+        } else if (mode == WINDOW_MODE) {
+            return mController.getWindowMagnificationMgr().reset(displayId);
+        }
+        return false;
     }
 
     /**
      * {@link FullScreenMagnificationController#resetIfNeeded(int, boolean)}
      */
+    // TODO: support window magnification
     public void resetAllIfNeeded(int connectionId) {
         mController.getFullScreenMagnificationController().resetAllIfNeeded(connectionId);
     }
 
     /**
+     * {@link FullScreenMagnificationController#isMagnifying(int)}
+     * {@link WindowMagnificationManager#isWindowMagnifierEnabled(int)}
+     */
+    public boolean isMagnifying(int displayId) {
+        int mode = getControllingMode(displayId);
+        if (mode == FULLSCREEN_MODE) {
+            return mController.getFullScreenMagnificationController().isMagnifying(displayId);
+        } else if (mode == WINDOW_MODE) {
+            return mController.getWindowMagnificationMgr().isWindowMagnifierEnabled(displayId);
+        }
+        return false;
+    }
+
+    /**
+     * Returns the current controlling magnification mode on the given display.
+     * If there is no magnifier activated, it fallbacks to the last activated mode.
+     * And the last activated mode is {@link FULLSCREEN_MODE} by default.
+     *
+     * @param displayId The logical display id
+     */
+    public int getControllingMode(int displayId) {
+        if (mController.isActivated(displayId,
+                ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)) {
+            return WINDOW_MODE;
+        } else if (mController.isActivated(displayId,
+                ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN)) {
+            return FULLSCREEN_MODE;
+        } else {
+            return (mController.getLastActivatedMode() == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW)
+                    ? WINDOW_MODE
+                    : FULLSCREEN_MODE;
+        }
+    }
+
+    private boolean registerDisplayMagnificationIfNeeded(int displayId,
+            boolean canControlMagnification) {
+        if (!isRegistered(displayId) && canControlMagnification) {
+            register(displayId);
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isRegistered(int displayId) {
+        return mController.getFullScreenMagnificationController().isRegistered(displayId);
+    }
+
+    /**
      * {@link FullScreenMagnificationController#register(int)}
      */
-    public void register(int displayId) {
+    private void register(int displayId) {
         mController.getFullScreenMagnificationController().register(displayId);
     }
 
     /**
      * {@link FullScreenMagnificationController#unregister(int)} (int)}
      */
-    public void unregister(int displayId) {
+    private void unregister(int displayId) {
         mController.getFullScreenMagnificationController().unregister(displayId);
     }
-
-    /**
-     * {@link FullScreenMagnificationController#isMagnifying(int)}
-     */
-    public boolean isMagnifying(int displayId) {
-        return mController.getFullScreenMagnificationController().isMagnifying(displayId);
-    }
-
-    /**
-     * {@link FullScreenMagnificationController#isRegistered(int)}
-     */
-    public boolean isRegistered(int displayId) {
-        return mController.getFullScreenMagnificationController().isRegistered(displayId);
-    }
-
-    private boolean registerMagnificationIfNeeded(int displayId, boolean canControlMagnification) {
-        if (!isRegistered(displayId) && canControlMagnification) {
-            register(displayId);
-            return true;
-        }
-        return false;
-    }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java
index 5277425..25dcc2a 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapper.java
@@ -59,15 +59,19 @@
     }
 
     boolean enableWindowMagnification(int displayId, float scale, float centerX, float centerY,
+            float magnificationFrameOffsetRatioX, float magnificationFrameOffsetRatioY,
             @Nullable MagnificationAnimationCallback callback) {
         if (mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MAGNIFICATION_CONNECTION)) {
             mTrace.logTrace(TAG + ".enableWindowMagnification",
                     FLAGS_WINDOW_MAGNIFICATION_CONNECTION,
                     "displayId=" + displayId + ";scale=" + scale + ";centerX=" + centerX
-                    + ";centerY=" + centerY + ";callback=" + callback);
+                            + ";centerY=" + centerY + ";magnificationFrameOffsetRatioX="
+                            + magnificationFrameOffsetRatioX + ";magnificationFrameOffsetRatioY="
+                            + magnificationFrameOffsetRatioY + ";callback=" + callback);
         }
         try {
             mConnection.enableWindowMagnification(displayId, scale, centerX, centerY,
+                    magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY,
                     transformToRemoteCallback(callback, mTrace));
         } catch (RemoteException e) {
             if (DBG) {
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
index 7d8f545..820be28 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationGestureHandler.java
@@ -18,6 +18,7 @@
 
 import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
 import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_MOVE;
 import static android.view.MotionEvent.ACTION_UP;
 
 import static java.util.Arrays.asList;
@@ -78,6 +79,8 @@
     final DetectingState mDetectingState;
     @VisibleForTesting
     final PanningScalingGestureState mObservePanningScalingState;
+    @VisibleForTesting
+    final ViewportDraggingState mViewportDraggingState;
 
     @VisibleForTesting
     State mCurrentState;
@@ -105,6 +108,7 @@
                         policyFlags));
         mDelegatingState = new DelegatingState(mMotionEventDispatcherDelegate);
         mDetectingState = new DetectingState(context, mDetectTripleTap);
+        mViewportDraggingState = new ViewportDraggingState();
         mObservePanningScalingState = new PanningScalingGestureState(
                 new PanningScalingHandler(context, MAX_SCALE, MIN_SCALE, true,
                         new PanningScalingHandler.MagnificationDelegate() {
@@ -158,7 +162,8 @@
     public void handleShortcutTriggered() {
         final Point screenSize = mTempPoint;
         getScreenSize(mTempPoint);
-        toggleMagnification(screenSize.x / 2.0f, screenSize.y / 2.0f);
+        toggleMagnification(screenSize.x / 2.0f, screenSize.y / 2.0f,
+                WindowMagnificationManager.WINDOW_POSITION_AT_CENTER);
     }
 
     private  void getScreenSize(Point outSize) {
@@ -171,14 +176,17 @@
         return Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
     }
 
-    private void enableWindowMagnifier(float centerX, float centerY) {
+    private void enableWindowMagnifier(float centerX, float centerY,
+            @WindowMagnificationManager.WindowPosition int windowPosition) {
         if (DEBUG_ALL) {
-            Slog.i(mLogTag, "enableWindowMagnifier :" + centerX + ", " + centerY);
+            Slog.i(mLogTag, "enableWindowMagnifier :"
+                    + centerX + ", " + centerY + ", " + windowPosition);
         }
 
         final float scale = MathUtils.constrain(
                 mWindowMagnificationMgr.getPersistedScale(mDisplayId), MIN_SCALE, MAX_SCALE);
-        mWindowMagnificationMgr.enableWindowMagnification(mDisplayId, scale, centerX, centerY);
+        mWindowMagnificationMgr.enableWindowMagnification(mDisplayId, scale, centerX, centerY,
+                windowPosition);
     }
 
     private void disableWindowMagnifier() {
@@ -188,11 +196,12 @@
         mWindowMagnificationMgr.disableWindowMagnification(mDisplayId, false);
     }
 
-    private void toggleMagnification(float centerX, float centerY) {
+    private void toggleMagnification(float centerX, float centerY,
+            @WindowMagnificationManager.WindowPosition int windowPosition) {
         if (mWindowMagnificationMgr.isWindowMagnifierEnabled(mDisplayId)) {
             disableWindowMagnifier();
         } else {
-            enableWindowMagnifier(centerX, centerY);
+            enableWindowMagnifier(centerX, centerY, windowPosition);
         }
     }
 
@@ -200,7 +209,17 @@
         if (DEBUG_DETECTING) {
             Slog.i(mLogTag, "onTripleTap()");
         }
-        toggleMagnification(up.getX(), up.getY());
+        toggleMagnification(up.getX(), up.getY(),
+                WindowMagnificationManager.WINDOW_POSITION_AT_CENTER);
+    }
+
+    private void onTripleTapAndHold(MotionEvent up) {
+        if (DEBUG_DETECTING) {
+            Slog.i(mLogTag, "onTripleTapAndHold()");
+        }
+        enableWindowMagnifier(up.getX(), up.getY(),
+                WindowMagnificationManager.WINDOW_POSITION_AT_TOP_LEFT);
+        transitionTo(mViewportDraggingState);
     }
 
     void resetToDetectState() {
@@ -319,6 +338,65 @@
         }
     }
 
+
+    /**
+     * This class handles motion events when the event dispatcher has
+     * determined that the user is performing a single-finger drag of the
+     * magnification viewport.
+     *
+     * Leaving this state until receiving {@link MotionEvent#ACTION_UP}
+     * or {@link MotionEvent#ACTION_CANCEL}.
+     */
+    final class ViewportDraggingState implements State {
+
+        private float mLastX = Float.NaN;
+        private float mLastY = Float.NaN;
+
+        @Override
+        public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
+            final int action = event.getActionMasked();
+            switch (action) {
+                case ACTION_MOVE: {
+                    if (!Float.isNaN(mLastX) && !Float.isNaN(mLastY)) {
+                        float offsetX = event.getX() - mLastX;
+                        float offsetY = event.getY() - mLastY;
+                        mWindowMagnificationMgr.moveWindowMagnification(mDisplayId, offsetX,
+                                offsetY);
+                    }
+                    mLastX = event.getX();
+                    mLastY = event.getY();
+                }
+                break;
+
+                case ACTION_UP:
+                case ACTION_CANCEL: {
+                    mWindowMagnificationMgr.disableWindowMagnification(mDisplayId, true);
+                    transitionTo(mDetectingState);
+                }
+                    break;
+            }
+        }
+
+        @Override
+        public void clear() {
+            mLastX = Float.NaN;
+            mLastY = Float.NaN;
+        }
+
+        @Override
+        public void onExit() {
+            clear();
+        }
+
+        @Override
+        public String toString() {
+            return "ViewportDraggingState{"
+                    + "mLastX=" + mLastX
+                    + ",mLastY=" + mLastY
+                    + '}';
+        }
+    }
+
     /**
      * This class handles motion events in a duration to determine if the user is going to
      * manipulate the window magnifier or want to interact with current UI. The rule of leaving
@@ -405,6 +483,8 @@
                 transitionTo(mObservePanningScalingState);
             } else if (gestureId == MagnificationGestureMatcher.GESTURE_TRIPLE_TAP) {
                 onTripleTap(motionEvent);
+            } else if (gestureId == MagnificationGestureMatcher.GESTURE_TRIPLE_TAP_AND_HOLD) {
+                onTripleTapAndHold(motionEvent);
             } else {
                 mMotionEventDispatcherDelegate.sendDelayedMotionEvents(delayedEventQueue,
                         lastDownEventTime);
@@ -439,6 +519,7 @@
         return "WindowMagnificationGestureHandler{"
                 + "mDetectingState=" + mDetectingState
                 + ", mDelegatingState=" + mDelegatingState
+                + ", mViewportDraggingState=" + mViewportDraggingState
                 + ", mMagnifiedInteractionState=" + mObservePanningScalingState
                 + ", mCurrentState=" + State.nameOf(mCurrentState)
                 + ", mPreviousState=" + State.nameOf(mPreviousState)
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
index e1ec273..9162064 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/WindowMagnificationManager.java
@@ -20,13 +20,16 @@
 import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MAGNIFICATION_CONNECTION_CALLBACK;
 import static android.view.accessibility.MagnificationAnimationCallback.STUB_ANIMATION_CALLBACK;
 
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.graphics.PointF;
 import android.graphics.Rect;
+import android.graphics.Region;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -43,6 +46,9 @@
 import com.android.server.accessibility.AccessibilityTraceManager;
 import com.android.server.statusbar.StatusBarManagerInternal;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * A class to manipulate window magnification through {@link WindowMagnificationConnectionWrapper}
  * create by {@link #setConnection(IWindowMagnificationConnection)}. To set the connection with
@@ -57,6 +63,25 @@
 
     private static final String TAG = "WindowMagnificationMgr";
 
+    /**
+     * Indicate that the magnification window is at the magnification center.
+     */
+    public static final int WINDOW_POSITION_AT_CENTER = 0;
+
+    /**
+     * Indicate that the magnification window is at the top-left side of the magnification
+     * center. The offset is equal to a half of MirrorSurfaceView. So, the bottom-right corner
+     * of the window is at the magnification center.
+     */
+    public static final int WINDOW_POSITION_AT_TOP_LEFT = 1;
+
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "WINDOW_POSITION_AT_" }, value = {
+            WINDOW_POSITION_AT_CENTER,
+            WINDOW_POSITION_AT_TOP_LEFT
+    })
+    public @interface WindowPosition {}
+
     private final Object mLock = new Object();
     private final Context mContext;
     @VisibleForTesting
@@ -271,41 +296,88 @@
      *                or {@link Float#NaN} to leave unchanged.
      * @param centerY The screen-relative Y coordinate around which to center,
      *                or {@link Float#NaN} to leave unchanged.
+     * @return {@code true} if the magnification is enabled successfully.
      */
-    void enableWindowMagnification(int displayId, float scale, float centerX, float centerY) {
-        enableWindowMagnification(displayId, scale, centerX, centerY, STUB_ANIMATION_CALLBACK);
+    public boolean enableWindowMagnification(int displayId, float scale, float centerX,
+            float centerY) {
+        return enableWindowMagnification(displayId, scale, centerX, centerY,
+                STUB_ANIMATION_CALLBACK);
     }
 
     /**
-     * Enables window magnification with specified center and scale on the specified display and
+     * Enables window magnification with specified center and scale on the given display and
      * animating the transition.
      *
      * @param displayId The logical display id.
      * @param scale The target scale, must be >= 1.
-     * @param centerX The screen-relative X coordinate around which to center,
+     * @param centerX The screen-relative X coordinate around which to center for magnification,
      *                or {@link Float#NaN} to leave unchanged.
-     * @param centerY The screen-relative Y coordinate around which to center,
+     * @param centerY The screen-relative Y coordinate around which to center for magnification,
      *                or {@link Float#NaN} to leave unchanged.
      * @param animationCallback Called when the animation result is valid.
+     * @return {@code true} if the magnification is enabled successfully.
      */
-    void enableWindowMagnification(int displayId, float scale, float centerX, float centerY,
-            @Nullable MagnificationAnimationCallback animationCallback) {
+    public boolean enableWindowMagnification(int displayId, float scale, float centerX,
+            float centerY, @Nullable MagnificationAnimationCallback animationCallback) {
+        return enableWindowMagnification(displayId, scale, centerX, centerY, animationCallback,
+                WINDOW_POSITION_AT_CENTER);
+    }
+
+    /**
+     * Enables window magnification with specified center and scale on the given display and
+     * animating the transition.
+     *
+     * @param displayId The logical display id.
+     * @param scale The target scale, must be >= 1.
+     * @param centerX The screen-relative X coordinate around which to center for magnification,
+     *                or {@link Float#NaN} to leave unchanged.
+     * @param centerY The screen-relative Y coordinate around which to center for magnification,
+     *                or {@link Float#NaN} to leave unchanged.
+     * @param windowPosition Indicate the offset between window position and (centerX, centerY).
+     * @return {@code true} if the magnification is enabled successfully.
+     */
+    public boolean enableWindowMagnification(int displayId, float scale, float centerX,
+            float centerY, @WindowPosition int windowPosition) {
+        return enableWindowMagnification(displayId, scale, centerX, centerY,
+                STUB_ANIMATION_CALLBACK, windowPosition);
+    }
+
+    /**
+     * Enables window magnification with specified center and scale on the given display and
+     * animating the transition.
+     *
+     * @param displayId         The logical display id.
+     * @param scale             The target scale, must be >= 1.
+     * @param centerX           The screen-relative X coordinate around which to center for
+     *                          magnification, or {@link Float#NaN} to leave unchanged.
+     * @param centerY           The screen-relative Y coordinate around which to center for
+     *                          magnification, or {@link Float#NaN} to leave unchanged.
+     * @param animationCallback Called when the animation result is valid.
+     * @param windowPosition    Indicate the offset between window position and (centerX, centerY).
+     * @return {@code true} if the magnification is enabled successfully.
+     */
+    public boolean enableWindowMagnification(int displayId, float scale, float centerX,
+            float centerY, @Nullable MagnificationAnimationCallback animationCallback,
+            @WindowPosition int windowPosition) {
         final boolean enabled;
+        boolean previousEnabled;
         synchronized (mLock) {
             if (mConnectionWrapper == null) {
-                return;
+                return false;
             }
             WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
             if (magnifier == null) {
                 magnifier = createWindowMagnifier(displayId);
             }
+            previousEnabled = magnifier.mEnabled;
             enabled = magnifier.enableWindowMagnificationInternal(scale, centerX, centerY,
-                    animationCallback);
+                    animationCallback, windowPosition);
         }
 
-        if (enabled) {
+        if (enabled && !previousEnabled) {
             mCallback.onWindowMagnificationActivationState(displayId, true);
         }
+        return enabled;
     }
 
     /**
@@ -464,7 +536,7 @@
      * @param displayId The logical display id
      * @return the X coordinate. {@link Float#NaN} if the window magnification is not enabled.
      */
-    float getCenterX(int displayId) {
+    public float getCenterX(int displayId) {
         synchronized (mLock) {
             WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
             if (magnifier == null) {
@@ -480,7 +552,7 @@
      * @param displayId The logical display id
      * @return the Y coordinate. {@link Float#NaN} if the window magnification is not enabled.
      */
-    float getCenterY(int displayId) {
+    public float getCenterY(int displayId) {
         synchronized (mLock) {
             WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
             if (magnifier == null) {
@@ -491,6 +563,42 @@
     }
 
     /**
+     * Populates magnified bounds on the screen. And the populated magnified bounds would be
+     * empty If window magnifier is not activated.
+     *
+     * @param displayId The logical display id.
+     * @param outRegion the region to populate
+     */
+    public void getMagnificationSourceBounds(int displayId, @NonNull Region outRegion) {
+        synchronized (mLock) {
+            WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
+            if (magnifier == null) {
+                outRegion.setEmpty();
+            } else {
+                outRegion.set(magnifier.mSourceBounds);
+            }
+        }
+    }
+
+    /**
+     * Resets the magnification scale and center.
+     *
+     * @param displayId The logical display id.
+     * @return {@code true} if the magnification spec changed, {@code false} if
+     * the spec did not change
+     */
+    public boolean reset(int displayId) {
+        synchronized (mLock) {
+            WindowMagnifier magnifier = mWindowMagnifiers.get(displayId);
+            if (magnifier == null) {
+                return false;
+            }
+            magnifier.reset();
+            return true;
+        }
+    }
+
+    /**
      * Creates the windowMagnifier based on the specified display and stores it.
      *
      * @param displayId logical display id.
@@ -618,6 +726,8 @@
         // The magnified bounds on the screen.
         private final Rect mSourceBounds = new Rect();
 
+        private PointF mMagnificationFrameOffsetRatio = new PointF(0f, 0f);
+
         WindowMagnifier(int displayId, WindowMagnificationManager windowMagnificationManager) {
             mDisplayId = displayId;
             mWindowMagnificationManager = windowMagnificationManager;
@@ -625,13 +735,17 @@
 
         @GuardedBy("mLock")
         boolean enableWindowMagnificationInternal(float scale, float centerX, float centerY,
-                @Nullable MagnificationAnimationCallback animationCallback) {
-            if (mEnabled) {
-                return false;
+                @Nullable MagnificationAnimationCallback animationCallback,
+                @WindowPosition int windowPosition) {
+            // Handle defaults. The scale may be NAN when just updating magnification center.
+            if (Float.isNaN(scale)) {
+                scale = getScale();
             }
             final float normScale = MagnificationScaleProvider.constrainScale(scale);
+            setMagnificationFrameOffsetRatioByWindowPosition(windowPosition);
             if (mWindowMagnificationManager.enableWindowMagnificationInternal(mDisplayId, normScale,
-                    centerX, centerY, animationCallback)) {
+                    centerX, centerY, mMagnificationFrameOffsetRatio.x,
+                    mMagnificationFrameOffsetRatio.y, animationCallback)) {
                 mScale = normScale;
                 mEnabled = true;
 
@@ -640,6 +754,19 @@
             return false;
         }
 
+        void setMagnificationFrameOffsetRatioByWindowPosition(@WindowPosition int windowPosition) {
+            switch (windowPosition) {
+                case WINDOW_POSITION_AT_CENTER: {
+                    mMagnificationFrameOffsetRatio.set(0f, 0f);
+                }
+                break;
+                case WINDOW_POSITION_AT_TOP_LEFT: {
+                    mMagnificationFrameOffsetRatio.set(-1f, -1f);
+                }
+                break;
+            }
+        }
+
         @GuardedBy("mLock")
         boolean disableWindowMagnificationInternal(
                 @Nullable MagnificationAnimationCallback animationResultCallback) {
@@ -723,9 +850,15 @@
     }
 
     private boolean enableWindowMagnificationInternal(int displayId, float scale, float centerX,
-            float centerY, MagnificationAnimationCallback animationCallback) {
-        return mConnectionWrapper != null && mConnectionWrapper.enableWindowMagnification(
-                displayId, scale, centerX, centerY, animationCallback);
+            float centerY, float magnificationFrameOffsetRatioX,
+            float magnificationFrameOffsetRatioY,
+            MagnificationAnimationCallback animationCallback) {
+        synchronized (mLock) {
+            return mConnectionWrapper != null && mConnectionWrapper.enableWindowMagnification(
+                    displayId, scale, centerX, centerY,
+                    magnificationFrameOffsetRatioX, magnificationFrameOffsetRatioY,
+                    animationCallback);
+        }
     }
 
     private boolean setScaleInternal(int displayId, float scale) {
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 5e2449d..422749e 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -210,7 +210,7 @@
         final IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         context.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler(),
-                Context.RECEIVER_NOT_EXPORTED);
+                Context.RECEIVER_EXPORTED);
 
         mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(getContext(),
                 com.android.internal.R.string.config_defaultAugmentedAutofillService);
diff --git a/services/backup/backuplib/java/com/android/server/backup/transport/DelegatingTransport.java b/services/backup/backuplib/java/com/android/server/backup/transport/DelegatingTransport.java
deleted file mode 100644
index ab87080..0000000
--- a/services/backup/backuplib/java/com/android/server/backup/transport/DelegatingTransport.java
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.backup.transport;
-
-import android.app.backup.BackupAgent;
-import android.app.backup.BackupTransport;
-import android.app.backup.RestoreDescription;
-import android.app.backup.RestoreSet;
-import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-
-import com.android.internal.backup.IBackupTransport;
-
-/**
- * Delegates all transport methods to the delegate() implemented in the derived class.
- */
-public abstract class DelegatingTransport extends IBackupTransport.Stub {
-    protected abstract IBackupTransport getDelegate() throws RemoteException;
-
-    /**
-     * Ask the transport for the name under which it should be registered.  This will
-     * typically be its host service's component name, but need not be.
-     */
-    @Override
-    public String name() throws RemoteException {
-        return getDelegate().name();
-    }
-
-    /**
-     * Ask the transport for an Intent that can be used to launch any internal
-     * configuration Activity that it wishes to present.  For example, the transport
-     * may offer a UI for allowing the user to supply login credentials for the
-     * transport's off-device backend.
-     *
-     * If the transport does not supply any user-facing configuration UI, it should
-     * return null from this method.
-     *
-     * @return An Intent that can be passed to Context.startActivity() in order to
-     * launch the transport's configuration UI.  This method will return null
-     * if the transport does not offer any user-facing configuration UI.
-     */
-    @Override
-    public Intent configurationIntent() throws RemoteException {
-        return getDelegate().configurationIntent();
-    }
-
-    /**
-     * On demand, supply a one-line string that can be shown to the user that
-     * describes the current backend destination.  For example, a transport that
-     * can potentially associate backup data with arbitrary user accounts should
-     * include the name of the currently-active account here.
-     *
-     * @return A string describing the destination to which the transport is currently
-     * sending data.  This method should not return null.
-     */
-    @Override
-    public String currentDestinationString() throws RemoteException {
-        return getDelegate().currentDestinationString();
-    }
-
-    /**
-     * Ask the transport for an Intent that can be used to launch a more detailed
-     * secondary data management activity.  For example, the configuration intent might
-     * be one for allowing the user to select which account they wish to associate
-     * their backups with, and the management intent might be one which presents a
-     * UI for managing the data on the backend.
-     *
-     * <p>In the Settings UI, the configuration intent will typically be invoked
-     * when the user taps on the preferences item labeled with the current
-     * destination string, and the management intent will be placed in an overflow
-     * menu labelled with the management label string.
-     *
-     * <p>If the transport does not supply any user-facing data management
-     * UI, then it should return {@code null} from this method.
-     *
-     * @return An intent that can be passed to Context.startActivity() in order to
-     * launch the transport's data-management UI.  This method will return
-     * {@code null} if the transport does not offer any user-facing data
-     * management UI.
-     */
-    @Override
-    public Intent dataManagementIntent() throws RemoteException {
-        return getDelegate().dataManagementIntent();
-    }
-
-    /**
-     * On demand, supply a short {@link CharSequence} that can be shown to the user as the
-     * label on
-     * an overflow menu item used to invoke the data management UI.
-     *
-     * @return A {@link CharSequence} to be used as the label for the transport's data management
-     *         affordance.  If the transport supplies a data management intent, this
-     *         method must not return {@code null}.
-     */
-    @Override
-    public CharSequence dataManagementIntentLabel() throws RemoteException {
-        return getDelegate().dataManagementIntentLabel();
-    }
-
-    /**
-     * Ask the transport where, on local device storage, to keep backup state blobs.
-     * This is per-transport so that mock transports used for testing can coexist with
-     * "live" backup services without interfering with the live bookkeeping.  The
-     * returned string should be a name that is expected to be unambiguous among all
-     * available backup transports; the name of the class implementing the transport
-     * is a good choice.  This MUST be constant.
-     *
-     * @return A unique name, suitable for use as a file or directory name, that the
-     *         Backup Manager could use to disambiguate state files associated with
-     *         different backup transports.
-     */
-    @Override
-    public String transportDirName() throws RemoteException {
-        return getDelegate().transportDirName();
-    }
-
-    /**
-     * Verify that this is a suitable time for a backup pass.  This should return zero
-     * if a backup is reasonable right now, some positive value otherwise.  This method
-     * will be called outside of the {@link #startSession}/{@link #endSession} pair.
-     *
-     * <p>If this is not a suitable time for a backup, the transport should return a
-     * backoff delay, in milliseconds, after which the Backup Manager should try again.
-     *
-     * @return Zero if this is a suitable time for a backup pass, or a positive time delay
-     *   in milliseconds to suggest deferring the backup pass for a while.
-     */
-    @Override
-    public long requestBackupTime() throws RemoteException {
-        return getDelegate().requestBackupTime();
-    }
-
-    /**
-     * Initialize the server side storage for this device, erasing all stored data.
-     * The transport may send the request immediately, or may buffer it.  After
-     * this is called, {@link #finishBackup} must be called to ensure the request
-     * is sent and received successfully.
-     *
-     * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far) or
-     *   {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure).
-     */
-    @Override
-    public int initializeDevice() throws RemoteException {
-        return getDelegate().initializeDevice();
-    }
-
-    /**
-     * Send one application's data to the backup destination.  The transport may send
-     * the data immediately, or may buffer it.  After this is called, {@link #finishBackup}
-     * must be called to ensure the data is sent and recorded successfully.
-     *
-     * @param packageInfo The identity of the application whose data is being backed up.
-     *   This specifically includes the signature list for the package.
-     * @param inFd Descriptor of file with data that resulted from invoking the application's
-     *   BackupService.doBackup() method.  This may be a pipe rather than a file on
-     *   persistent media, so it may not be seekable.
-     * @param flags Some of {@link BackupTransport#FLAG_USER_INITIATED}.
-     * @return one of {@link BackupConstants#TRANSPORT_OK} (OK so far),
-     *  {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure), or
-     *  {@link BackupConstants#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has
-     *  become lost due to inactive expiry or some other reason and needs re-initializing)
-     */
-    @Override
-    public int performBackup(PackageInfo packageInfo,
-            ParcelFileDescriptor inFd, int flags) throws RemoteException {
-        return getDelegate().performBackup(packageInfo, inFd, flags);
-    }
-
-    /**
-     * Erase the give application's data from the backup destination.  This clears
-     * out the given package's data from the current backup set, making it as though
-     * the app had never yet been backed up.  After this is called, {@link finishBackup}
-     * must be called to ensure that the operation is recorded successfully.
-     *
-     * @return the same error codes as {@link #performBackup}.
-     * @param packageInfo
-     */
-    @Override
-    public int clearBackupData(PackageInfo packageInfo) throws RemoteException {
-        return getDelegate().clearBackupData(packageInfo);
-    }
-
-    /**
-     * Finish sending application data to the backup destination.  This must be
-     * called after {@link #performBackup} or {@link clearBackupData} to ensure that
-     * all data is sent.  Only when this method returns true can a backup be assumed
-     * to have succeeded.
-     *
-     * @return the same error codes as {@link #performBackup}.
-     */
-    @Override
-    public int finishBackup() throws RemoteException {
-        return getDelegate().finishBackup();
-    }
-
-    /**
-     * Get the set of all backups currently available over this transport.
-     *
-     * @return Descriptions of the set of restore images available for this device,
-     *   or null if an error occurred (the attempt should be rescheduled).
-     **/
-    @Override
-    public RestoreSet[] getAvailableRestoreSets() throws RemoteException {
-        return getDelegate().getAvailableRestoreSets();
-    }
-
-    /**
-     * Get the identifying token of the backup set currently being stored from
-     * this device.  This is used in the case of applications wishing to restore
-     * their last-known-good data.
-     *
-     * @return A token that can be passed to {@link #startRestore}, or 0 if there
-     *   is no backup set available corresponding to the current device state.
-     */
-    @Override
-    public long getCurrentRestoreSet() throws RemoteException {
-        return getDelegate().getCurrentRestoreSet();
-    }
-
-    /**
-     * Start restoring application data from backup.  After calling this function,
-     * alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData}
-     * to walk through the actual application data.
-     *
-     * @param token A backup token as returned by {@link #getAvailableRestoreSets}
-     *   or {@link #getCurrentRestoreSet}.
-     * @param packages List of applications to restore (if data is available).
-     *   Application data will be restored in the order given.
-     * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far, call
-     *   {@link #nextRestorePackage}) or {@link BackupConstants#TRANSPORT_ERROR}
-     *   (an error occurred, the restore should be aborted and rescheduled).
-     */
-    @Override
-    public int startRestore(long token, PackageInfo[] packages) throws RemoteException {
-        return getDelegate().startRestore(token, packages);
-    }
-
-    /**
-     * Get the package name of the next application with data in the backup store, plus
-     * a description of the structure of the restored archive: either TYPE_KEY_VALUE for
-     * an original-API key/value dataset, or TYPE_FULL_STREAM for a tarball-type archive stream.
-     *
-     * <p>If the package name in the returned RestoreDescription object is the singleton
-     * {@link RestoreDescription#NO_MORE_PACKAGES}, it indicates that no further data is available
-     * in the current restore session: all packages described in startRestore() have been
-     * processed.
-     *
-     * <p>If this method returns {@code null}, it means that a transport-level error has
-     * occurred and the entire restore operation should be abandoned.
-     *
-     * @return A RestoreDescription object containing the name of one of the packages
-     *   supplied to {@link #startRestore} plus an indicator of the data type of that
-     *   restore data; or {@link RestoreDescription#NO_MORE_PACKAGES} to indicate that
-     *   no more packages can be restored in this session; or {@code null} to indicate
-     *   a transport-level error.
-     */
-    @Override
-    public RestoreDescription nextRestorePackage() throws RemoteException {
-        return getDelegate().nextRestorePackage();
-    }
-
-    /**
-     * Get the data for the application returned by {@link #nextRestorePackage}.
-     *
-     * @param outFd An open, writable file into which the backup data should be stored.
-     * @return the same error codes as {@link #startRestore}.
-     */
-    @Override
-    public int getRestoreData(ParcelFileDescriptor outFd) throws RemoteException {
-        return getDelegate().getRestoreData(outFd);
-    }
-
-    /**
-     * End a restore session (aborting any in-process data transfer as necessary),
-     * freeing any resources and connections used during the restore process.
-     */
-    @Override
-    public void finishRestore() throws RemoteException {
-        getDelegate().finishRestore();
-    }
-
-    @Override
-    public long requestFullBackupTime() throws RemoteException {
-        return getDelegate().requestFullBackupTime();
-    }
-
-    @Override
-    public int performFullBackup(PackageInfo targetPackage,
-            ParcelFileDescriptor socket, int flags) throws RemoteException {
-        return getDelegate().performFullBackup(targetPackage, socket, flags);
-    }
-
-    @Override
-    public int checkFullBackupSize(long size) throws RemoteException {
-        return getDelegate().checkFullBackupSize(size);
-    }
-
-    @Override
-    public int sendBackupData(int numBytes) throws RemoteException {
-        return getDelegate().sendBackupData(numBytes);
-    }
-
-    @Override
-    public void cancelFullBackup() throws RemoteException {
-        getDelegate().cancelFullBackup();
-    }
-
-    /**
-     * Ask the transport whether this app is eligible for backup.
-     *
-     * @param targetPackage The identity of the application.
-     * @param isFullBackup If set, transport should check if app is eligible for full data backup,
-     *   otherwise to check if eligible for key-value backup.
-     * @return Whether this app is eligible for backup.
-     */
-    @Override
-    public boolean isAppEligibleForBackup(PackageInfo targetPackage,
-            boolean isFullBackup) throws RemoteException {
-        return getDelegate().isAppEligibleForBackup(targetPackage, isFullBackup);
-    }
-
-    /**
-     * Ask the transport about current quota for backup size of the package.
-     *
-     * @param packageName  ID of package to provide the quota.
-     * @param isFullBackup If set, transport should return limit for full data backup, otherwise
-     *                     for key-value backup.
-     * @return Current limit on full data backup size in bytes.
-     */
-    @Override
-    public long getBackupQuota(String packageName, boolean isFullBackup) throws RemoteException {
-        return getDelegate().getBackupQuota(packageName, isFullBackup);
-    }
-
-    /**
-     * Ask the transport to provide data for the "current" package being restored.  This
-     * is the package that was just reported by {@link #nextRestorePackage()} as having
-     * {@link RestoreDescription#TYPE_FULL_STREAM} data.
-     *
-     * The transport writes some data to the socket supplied to this call, and returns
-     * the number of bytes written.  The system will then read that many bytes and
-     * stream them to the application's agent for restore, then will call this method again
-     * to receive the next chunk of the archive.  This sequence will be repeated until the
-     * transport returns zero indicating that all of the package's data has been delivered
-     * (or returns a negative value indicating some sort of hard error condition at the
-     * transport level).
-     *
-     * <p>After this method returns zero, the system will then call
-     * {@link #getNextFullRestorePackage()} to begin the restore process for the next
-     * application, and the sequence begins again.
-     *
-     * <p>The transport should always close this socket when returning from this method.
-     * Do not cache this socket across multiple calls or you may leak file descriptors.
-     *
-     * @param socket The file descriptor that the transport will use for delivering the
-     *    streamed archive.  The transport must close this socket in all cases when returning
-     *    from this method.
-     * @return 0 when no more data for the current package is available.  A positive value
-     *    indicates the presence of that many bytes to be delivered to the app.  Any negative
-     *    return value is treated as equivalent to {@link BackupTransport#TRANSPORT_ERROR},
-     *    indicating a fatal error condition that precludes further restore operations
-     *    on the current dataset.
-     */
-    @Override
-    public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) throws RemoteException {
-        return getDelegate().getNextFullRestoreDataChunk(socket);
-    }
-
-    /**
-     * If the OS encounters an error while processing {@link RestoreDescription#TYPE_FULL_STREAM}
-     * data for restore, it will invoke this method to tell the transport that it should
-     * abandon the data download for the current package.  The OS will then either call
-     * {@link #nextRestorePackage()} again to move on to restoring the next package in the
-     * set being iterated over, or will call {@link #finishRestore()} to shut down the restore
-     * operation.
-     *
-     * @return {@link #TRANSPORT_OK} if the transport was successful in shutting down the
-     *    current stream cleanly, or {@link #TRANSPORT_ERROR} to indicate a serious
-     *    transport-level failure.  If the transport reports an error here, the entire restore
-     *    operation will immediately be finished with no further attempts to restore app data.
-     */
-    @Override
-    public int abortFullRestore() throws RemoteException {
-        return getDelegate().abortFullRestore();
-    }
-
-    /**
-     * Returns flags with additional information about the transport, which is accessible to the
-     * {@link BackupAgent}. This allows the agent to decide what to backup or
-     * restore based on properties of the transport.
-     *
-     * <p>For supported flags see {@link BackupAgent}.
-     */
-    @Override
-    public int getTransportFlags() throws RemoteException {
-        return getDelegate().getTransportFlags();
-    }
-}
diff --git a/services/backup/backuplib/java/com/android/server/backup/transport/TransportClientManager.java b/services/backup/backuplib/java/com/android/server/backup/transport/TransportClientManager.java
index 72b1ee7..f907e08 100644
--- a/services/backup/backuplib/java/com/android/server/backup/transport/TransportClientManager.java
+++ b/services/backup/backuplib/java/com/android/server/backup/transport/TransportClientManager.java
@@ -41,12 +41,6 @@
  */
 public class TransportClientManager {
     private static final String TAG = "TransportClientManager";
-    private static final String SERVICE_ACTION_ENCRYPTING_TRANSPORT =
-            "android.encryption.BACKUP_ENCRYPTION";
-    private static final ComponentName ENCRYPTING_TRANSPORT = new ComponentName(
-            "com.android.server.backup.encryption",
-            "com.android.server.backup.encryption.BackupEncryptionService");
-    private static final String ENCRYPTING_TRANSPORT_REAL_TRANSPORT_KEY = "transport";
 
     private final @UserIdInt int mUserId;
     private final Context mContext;
@@ -57,17 +51,6 @@
     private final Function<ComponentName, Intent> mIntentFunction;
 
     /**
-     * Return an {@link Intent} which resolves to an intermediate {@link IBackupTransport} that
-     * encrypts (or decrypts) the data when sending it (or receiving it) from the {@link
-     * IBackupTransport} for the given {@link ComponentName}.
-     */
-    public static Intent getEncryptingTransportIntent(ComponentName tranportComponent) {
-        return new Intent(SERVICE_ACTION_ENCRYPTING_TRANSPORT)
-                .setComponent(ENCRYPTING_TRANSPORT)
-                .putExtra(ENCRYPTING_TRANSPORT_REAL_TRANSPORT_KEY, tranportComponent);
-    }
-
-    /**
      * Return an {@link Intent} which resolves to the {@link IBackupTransport} for the {@link
      * ComponentName}.
      */
@@ -75,32 +58,6 @@
         return new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(transportComponent);
     }
 
-    /**
-     * Given a {@link Intent} originally created by {@link
-     * #getEncryptingTransportIntent(ComponentName)}, returns the {@link Intent} which resolves to
-     * the {@link IBackupTransport} for that {@link ComponentName}.
-     */
-    public static Intent getRealTransportIntent(Intent encryptingTransportIntent) {
-        ComponentName transportComponent = encryptingTransportIntent.getParcelableExtra(
-                ENCRYPTING_TRANSPORT_REAL_TRANSPORT_KEY);
-        Intent intent = getRealTransportIntent(transportComponent)
-                .putExtras(encryptingTransportIntent.getExtras());
-        intent.removeExtra(ENCRYPTING_TRANSPORT_REAL_TRANSPORT_KEY);
-        return intent;
-    }
-
-    /**
-     * Create a {@link TransportClientManager} such that {@link #getTransportClient(ComponentName,
-     * Bundle, String)} returns a {@link TransportClient} which connects to an intermediate {@link
-     * IBackupTransport} that encrypts (or decrypts) the data when sending it (or receiving it) from
-     * the {@link IBackupTransport} for the given {@link ComponentName}.
-     */
-    public static TransportClientManager createEncryptingClientManager(@UserIdInt int userId,
-            Context context, TransportStats transportStats) {
-        return new TransportClientManager(userId, context, transportStats,
-                TransportClientManager::getEncryptingTransportIntent);
-    }
-
     public TransportClientManager(@UserIdInt int userId, Context context,
             TransportStats transportStats) {
         this(userId, context, transportStats, TransportClientManager::getRealTransportIntent);
diff --git a/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
index 2645f3f..7d22e9a 100644
--- a/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
+++ b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
@@ -16,29 +16,26 @@
 
 package com.android.server.companion;
 
-import static android.companion.AssociationRequest.DEVICE_PROFILE_APP_STREAMING;
-import static android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION;
-import static android.companion.AssociationRequest.DEVICE_PROFILE_WATCH;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
 import static com.android.internal.util.CollectionUtils.filter;
 import static com.android.internal.util.FunctionalUtils.uncheckExceptions;
-import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.server.companion.CompanionDeviceManagerService.DEBUG;
 import static com.android.server.companion.CompanionDeviceManagerService.LOG_TAG;
-import static com.android.server.companion.CompanionDeviceManagerService.getCallingUserId;
+import static com.android.server.companion.PermissionsUtils.enforceCallerCanInteractWithUserId;
+import static com.android.server.companion.PermissionsUtils.enforceCallerIsSystemOr;
+import static com.android.server.companion.PermissionsUtils.enforceRequestDeviceProfilePermissions;
+import static com.android.server.companion.PermissionsUtils.enforceRequestSelfManagedPermission;
+import static com.android.server.companion.RolesUtils.isRoleHolder;
 
-import static java.util.Collections.unmodifiableMap;
+import static java.util.Objects.requireNonNull;
 
-import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.role.RoleManager;
+import android.annotation.UserIdInt;
 import android.companion.AssociationInfo;
 import android.companion.AssociationRequest;
 import android.companion.CompanionDeviceManager;
+import android.companion.IAssociationRequestCallback;
 import android.companion.ICompanionDeviceDiscoveryService;
-import android.companion.IFindDeviceCallback;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -46,8 +43,6 @@
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
-import android.os.UserHandle;
-import android.util.ArrayMap;
 import android.util.PackageUtils;
 import android.util.Slog;
 
@@ -60,26 +55,12 @@
 import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
 class AssociationRequestsProcessor {
     private static final String TAG = LOG_TAG + ".AssociationRequestsProcessor";
 
-    private static final Map<String, String> DEVICE_PROFILE_TO_PERMISSION;
-    static {
-        final Map<String, String> map = new ArrayMap<>();
-        map.put(DEVICE_PROFILE_WATCH, Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH);
-        map.put(DEVICE_PROFILE_APP_STREAMING,
-                Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING);
-        map.put(DEVICE_PROFILE_AUTOMOTIVE_PROJECTION,
-                Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION);
-
-        DEVICE_PROFILE_TO_PERMISSION = unmodifiableMap(map);
-    }
-
     private static final ComponentName SERVICE_TO_BIND_TO = ComponentName.createRelative(
             CompanionDeviceManager.COMPANION_DEVICE_DISCOVERY_PACKAGE_NAME,
             ".CompanionDeviceDiscoveryService");
@@ -89,19 +70,15 @@
 
     private final Context mContext;
     private final CompanionDeviceManagerService mService;
+    private final PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>> mServiceConnectors;
 
     private AssociationRequest mRequest;
-    private IFindDeviceCallback mFindDeviceCallback;
-    private String mCallingPackage;
+    private IAssociationRequestCallback mAppCallback;
     private AndroidFuture<?> mOngoingDeviceDiscovery;
-    private RoleManager mRoleManager;
 
-    private PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>> mServiceConnectors;
-
-    AssociationRequestsProcessor(CompanionDeviceManagerService service, RoleManager roleManager) {
+    AssociationRequestsProcessor(CompanionDeviceManagerService service) {
         mContext = service.getContext();
         mService = service;
-        mRoleManager = roleManager;
 
         final Intent serviceIntent = new Intent().setComponent(SERVICE_TO_BIND_TO);
         mServiceConnectors = new PerUser<ServiceConnector<ICompanionDeviceDiscoveryService>>() {
@@ -115,30 +92,63 @@
         };
     }
 
-    void process(AssociationRequest request, IFindDeviceCallback callback, String callingPackage)
-            throws RemoteException {
+    /**
+     * Handle incoming {@link AssociationRequest}s, sent via
+     * {@link android.companion.ICompanionDeviceManager#associate(AssociationRequest, IAssociationRequestCallback, String, int)}
+     */
+    void process(@NonNull AssociationRequest request, @NonNull String packageName,
+            @UserIdInt int userId, @NonNull IAssociationRequestCallback callback) {
+        requireNonNull(request, "Request MUST NOT be null");
+        requireNonNull(packageName, "Package name MUST NOT be null");
+        requireNonNull(callback, "Callback MUST NOT be null");
+
         if (DEBUG) {
-            Slog.d(TAG, "process(request=" + request + ", from=" + callingPackage + ")");
+            Slog.d(TAG, "process() "
+                    + "request=" + request + ", "
+                    + "package=u" + userId + "/" + packageName);
         }
 
-        checkNotNull(request, "Request cannot be null");
-        checkNotNull(callback, "Callback cannot be null");
-        mService.checkCallerIsSystemOr(callingPackage);
-        int userId = getCallingUserId();
-        mService.checkUsesFeature(callingPackage, userId);
+        enforceCallerCanInteractWithUserId(mContext, userId);
+        enforceCallerIsSystemOr(userId, packageName);
+
+        mService.checkUsesFeature(packageName, userId);
+
+        if (request.isSelfManaged()) {
+            enforceRequestSelfManagedPermission(mContext);
+        }
+
         final String deviceProfile = request.getDeviceProfile();
-        validateDeviceProfileAndCheckPermission(deviceProfile);
+        enforceRequestDeviceProfilePermissions(mContext, deviceProfile);
 
-        mFindDeviceCallback = callback;
-        mRequest = request;
-        mCallingPackage = callingPackage;
-        request.setCallingPackage(callingPackage);
+        synchronized (mService.mLock) {
+            if (mRequest != null) {
+                Slog.w(TAG, "CDM is already processing another AssociationRequest.");
 
-        if (mayAssociateWithoutPrompt(callingPackage, userId)) {
+                try {
+                    callback.onFailure("Busy.");
+                } catch (RemoteException e) {
+                    // OK to ignore.
+                }
+                return;
+            }
+
+            try {
+                callback.asBinder().linkToDeath(mBinderDeathRecipient /* recipient */, 0);
+            } catch (RemoteException e) {
+                // The process has died by now: do not proceed.
+                return;
+            }
+
+            mRequest = request;
+        }
+
+        mAppCallback = callback;
+        request.setCallingPackage(packageName);
+
+        if (mayAssociateWithoutPrompt(packageName, userId)) {
             Slog.i(TAG, "setSkipPrompt(true)");
             request.setSkipPrompt(true);
         }
-        callback.asBinder().linkToDeath(mBinderDeathRecipient /* recipient */, 0);
 
         mOngoingDeviceDiscovery = getDeviceProfilePermissionDescription(deviceProfile)
                 .thenComposeAsync(description -> {
@@ -155,17 +165,16 @@
                         }
 
                         AndroidFuture<String> future = new AndroidFuture<>();
-                        service.startDiscovery(request, callingPackage, callback, future);
+                        service.startDiscovery(request, packageName, callback, future);
                         return future;
                     }).cancelTimeout();
 
                 }, FgThread.getExecutor()).whenComplete(uncheckExceptions((deviceAddress, err) -> {
                     if (err == null) {
                         mService.createAssociationInternal(
-                                userId, deviceAddress, callingPackage, deviceProfile);
-                        mServiceConnectors.forUser(userId).post(service -> {
-                            service.onAssociationCreated();
-                        });
+                                userId, deviceAddress, packageName, deviceProfile);
+                        mServiceConnectors.forUser(userId).post(
+                                ICompanionDeviceDiscoveryService::onAssociationCreated);
                     } else {
                         Slog.e(TAG, "Failed to discover device(s)", err);
                         callback.onFailure("No devices found: " + err.getMessage());
@@ -174,54 +183,6 @@
                 }));
     }
 
-    private boolean isRoleHolder(int userId, String packageName, String role) {
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            List<String> holders = mRoleManager.getRoleHoldersAsUser(role, UserHandle.of(userId));
-            return holders.contains(packageName);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    void stopScan(AssociationRequest request, IFindDeviceCallback callback, String callingPackage) {
-        if (DEBUG) {
-            Slog.d(TAG, "stopScan(request = " + request + ")");
-        }
-        if (Objects.equals(request, mRequest)
-                && Objects.equals(callback, mFindDeviceCallback)
-                && Objects.equals(callingPackage, mCallingPackage)) {
-            cleanup();
-        }
-    }
-
-    private void validateDeviceProfileAndCheckPermission(@Nullable String deviceProfile) {
-        // Device profile can be null.
-        if (deviceProfile == null) return;
-
-        if (DEVICE_PROFILE_APP_STREAMING.equals(deviceProfile)) {
-            // TODO: remove, when properly supporting this profile.
-            throw new UnsupportedOperationException(
-                    "DEVICE_PROFILE_APP_STREAMING is not fully supported yet.");
-        }
-
-        if (DEVICE_PROFILE_AUTOMOTIVE_PROJECTION.equals(deviceProfile)) {
-            // TODO: remove, when properly supporting this profile.
-            throw new UnsupportedOperationException(
-                    "DEVICE_PROFILE_AUTOMOTIVE_PROJECTION is not fully supported yet.");
-        }
-
-        if (!DEVICE_PROFILE_TO_PERMISSION.containsKey(deviceProfile)) {
-            throw new IllegalArgumentException("Unsupported device profile: " + deviceProfile);
-        }
-
-        final String permission = DEVICE_PROFILE_TO_PERMISSION.get(deviceProfile);
-        if (mContext.checkCallingOrSelfPermission(permission) != PERMISSION_GRANTED) {
-            throw new SecurityException("Application must hold " + permission + " to associate "
-                    + "with a device with " + deviceProfile + " profile.");
-        }
-    }
-
     private void cleanup() {
         if (DEBUG) {
             Slog.d(TAG, "cleanup(); discovery = "
@@ -232,20 +193,23 @@
             if (ongoingDeviceDiscovery != null && !ongoingDeviceDiscovery.isDone()) {
                 ongoingDeviceDiscovery.cancel(true);
             }
-            if (mFindDeviceCallback != null) {
-                mFindDeviceCallback.asBinder().unlinkToDeath(mBinderDeathRecipient, 0);
-                mFindDeviceCallback = null;
+            if (mAppCallback != null) {
+                mAppCallback.asBinder().unlinkToDeath(mBinderDeathRecipient, 0);
+                mAppCallback = null;
             }
             mRequest = null;
-            mCallingPackage = null;
         }
     }
 
     private boolean mayAssociateWithoutPrompt(String packageName, int userId) {
-        if (mRequest.getDeviceProfile() != null
-                && isRoleHolder(userId, packageName, mRequest.getDeviceProfile())) {
-            // Don't need to collect user's consent since app already holds the role.
-            return true;
+        final String deviceProfile = mRequest.getDeviceProfile();
+        if (deviceProfile != null) {
+            final boolean isRoleHolder = Binder.withCleanCallingIdentity(
+                    () -> isRoleHolder(mContext, userId, packageName, deviceProfile));
+            if (isRoleHolder) {
+                // Don't need to collect user's consent since app already holds the role.
+                return true;
+            }
         }
 
         String[] sameOemPackages = mContext.getResources()
@@ -261,7 +225,7 @@
         // Throttle frequent associations
         long now = System.currentTimeMillis();
         Set<AssociationInfo> recentAssociations = filter(
-                mService.getAllAssociations(userId, packageName),
+                mService.getAssociations(userId, packageName),
                 a -> now - a.getTimeApprovedMs() < ASSOCIATE_WITHOUT_PROMPT_WINDOW_MS);
 
         if (recentAssociations.size() >= ASSOCIATE_WITHOUT_PROMPT_MAX_PER_TIME_WINDOW) {
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index d5357dc..f8be165 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -17,11 +17,14 @@
 
 package com.android.server.companion;
 
+import static android.Manifest.permission.MANAGE_COMPANION_DEVICES;
 import static android.bluetooth.le.ScanSettings.CALLBACK_TYPE_ALL_MATCHES;
 import static android.bluetooth.le.ScanSettings.SCAN_MODE_BALANCED;
-import static android.companion.DeviceId.TYPE_MAC_ADDRESS;
 import static android.content.pm.PackageManager.CERT_INPUT_SHA256;
+import static android.content.pm.PackageManager.FEATURE_COMPANION_DEVICE_SETUP;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.UserHandle.getCallingUserId;
 
 import static com.android.internal.util.CollectionUtils.add;
 import static com.android.internal.util.CollectionUtils.any;
@@ -29,11 +32,16 @@
 import static com.android.internal.util.CollectionUtils.find;
 import static com.android.internal.util.CollectionUtils.forEach;
 import static com.android.internal.util.CollectionUtils.map;
-import static com.android.internal.util.Preconditions.checkArgument;
-import static com.android.internal.util.Preconditions.checkNotNull;
 import static com.android.internal.util.Preconditions.checkState;
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 import static com.android.internal.util.function.pooled.PooledLambda.obtainRunnable;
+import static com.android.server.companion.PermissionsUtils.checkCallerCanManageAssociationsForPackage;
+import static com.android.server.companion.PermissionsUtils.checkCallerCanManagerCompanionDevice;
+import static com.android.server.companion.PermissionsUtils.enforceCallerCanInteractWithUserId;
+import static com.android.server.companion.PermissionsUtils.enforceCallerCanManagerCompanionDevice;
+import static com.android.server.companion.PermissionsUtils.enforceCallerIsSystemOr;
+import static com.android.server.companion.RolesUtils.addRoleHolderForAssociation;
+import static com.android.server.companion.RolesUtils.removeRoleHolderForAssociation;
 
 import static java.util.Collections.emptySet;
 import static java.util.Collections.unmodifiableSet;
@@ -48,7 +56,6 @@
 import android.app.AppOpsManager;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.app.role.RoleManager;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothDevice;
 import android.bluetooth.le.BluetoothLeScanner;
@@ -58,10 +65,10 @@
 import android.bluetooth.le.ScanSettings;
 import android.companion.AssociationInfo;
 import android.companion.AssociationRequest;
-import android.companion.DeviceId;
 import android.companion.DeviceNotAssociatedException;
+import android.companion.IAssociationRequestCallback;
 import android.companion.ICompanionDeviceManager;
-import android.companion.IFindDeviceCallback;
+import android.companion.IOnAssociationsChangedListener;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -74,13 +81,13 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.UserInfo;
+import android.net.MacAddress;
 import android.net.NetworkPolicyManager;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Parcel;
 import android.os.PowerWhitelistManager;
-import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
@@ -117,7 +124,6 @@
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -159,7 +165,6 @@
     private final AssociationRequestsProcessor mAssociationRequestsProcessor;
     private PowerWhitelistManager mPowerWhitelistManager;
     private IAppOpsService mAppOpsManager;
-    private RoleManager mRoleManager;
     private BluetoothAdapter mBluetoothAdapter;
     private UserManager mUserManager;
 
@@ -202,7 +207,6 @@
         mPersistentDataStore = new PersistentDataStore();
 
         mPowerWhitelistManager = context.getSystemService(PowerWhitelistManager.class);
-        mRoleManager = context.getSystemService(RoleManager.class);
         mAppOpsManager = IAppOpsService.Stub.asInterface(
                 ServiceManager.getService(Context.APP_OPS_SERVICE));
         mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
@@ -212,7 +216,7 @@
                 context.getSystemService(PermissionControllerManager.class));
         mUserManager = context.getSystemService(UserManager.class);
         mCompanionDevicePresenceController = new CompanionDevicePresenceController();
-        mAssociationRequestsProcessor = new AssociationRequestsProcessor(this, mRoleManager);
+        mAssociationRequestsProcessor = new AssociationRequestsProcessor(this);
 
         registerPackageMonitor();
     }
@@ -221,26 +225,28 @@
         new PackageMonitor() {
             @Override
             public void onPackageRemoved(String packageName, int uid) {
-                Slog.d(LOG_TAG, "onPackageRemoved(packageName = " + packageName
-                        + ", uid = " + uid + ")");
-                int userId = getChangingUserId();
-                updateAssociations(
-                        set -> filterOut(set, it -> it.belongsToPackage(userId, packageName)),
-                        userId);
+                final int userId = getChangingUserId();
+                Slog.i(LOG_TAG, "onPackageRemoved() u" + userId + "/" + packageName);
 
-                mCompanionDevicePresenceController.unbindDevicePresenceListener(
-                        packageName, userId);
+                clearAssociationForPackage(userId, packageName);
+            }
+
+            @Override
+            public void onPackageDataCleared(String packageName, int uid) {
+                final int userId = getChangingUserId();
+                Slog.i(LOG_TAG, "onPackageDataCleared() u" + userId + "/" + packageName);
+
+                clearAssociationForPackage(userId, packageName);
             }
 
             @Override
             public void onPackageModified(String packageName) {
-                Slog.d(LOG_TAG, "onPackageModified(packageName = " + packageName + ")");
-                int userId = getChangingUserId();
-                forEach(getAllAssociations(userId, packageName), association -> {
-                    updateSpecialAccessPermissionForAssociatedPackage(association);
-                });
-            }
+                final int userId = getChangingUserId();
+                Slog.i(LOG_TAG, "onPackageModified() u" + userId + "/" + packageName);
 
+                forEach(getAssociations(userId, packageName), association ->
+                        updateSpecialAccessPermissionForAssociatedPackage(association));
+            }
         }.register(getContext(), FgThread.get().getLooper(), UserHandle.ALL, true);
     }
 
@@ -269,18 +275,82 @@
 
     @Override
     public void onUserUnlocking(@NonNull TargetUser user) {
-        int userHandle = user.getUserIdentifier();
-        Set<AssociationInfo> associations = getAllAssociations(userHandle);
-        if (associations == null || associations.isEmpty()) {
-            return;
-        }
-        updateAtm(userHandle, associations);
+        final int userId = user.getUserIdentifier();
+        final Set<AssociationInfo> associations = getAllAssociationsForUser(userId);
+
+        if (associations.isEmpty()) return;
+
+        updateAtm(userId, associations);
 
         BackgroundThread.getHandler().sendMessageDelayed(
                 obtainMessage(CompanionDeviceManagerService::maybeGrantAutoRevokeExemptions, this),
                 MINUTES.toMillis(10));
     }
 
+    @NonNull
+    Set<AssociationInfo> getAllAssociationsForUser(@UserIdInt int userId) {
+        synchronized (mLock) {
+            readPersistedStateForUserIfNeededLocked(userId);
+            // This returns non-null, because the readAssociationsInfoForUserIfNeededLocked() method
+            // we just called adds an empty set, if there was no previously saved data.
+            return mCachedAssociations.get(userId);
+        }
+    }
+
+    @NonNull
+    Set<AssociationInfo> getAssociations(@UserIdInt int userId, @NonNull String packageName) {
+        return filter(getAllAssociationsForUser(userId),
+                a -> a.belongsToPackage(userId, packageName));
+    }
+
+    @Nullable
+    private AssociationInfo getAssociation(int associationId) {
+        return find(getAllAssociations(), association -> association.getId() == associationId);
+    }
+
+    @Nullable
+    AssociationInfo getAssociation(
+            @UserIdInt int userId, @NonNull String packageName, @NonNull String macAddress) {
+        return find(getAssociations(userId, packageName), a -> a.isLinkedTo(macAddress));
+    }
+
+    @Nullable
+    AssociationInfo getAssociationWithCallerChecks(
+            @UserIdInt int userId, @NonNull String packageName, @NonNull String macAddress) {
+        return sanitizeWithCallerChecks(getAssociation(userId, packageName, macAddress));
+    }
+
+    @Nullable
+    AssociationInfo getAssociationWithCallerChecks(int associationId) {
+        return sanitizeWithCallerChecks(getAssociation(associationId));
+    }
+
+    @Nullable
+    private AssociationInfo sanitizeWithCallerChecks(@Nullable AssociationInfo association) {
+        if (association == null) return null;
+
+        final int userId = association.getUserId();
+        final String packageName = association.getPackageName();
+        if (!checkCallerCanManageAssociationsForPackage(getContext(), userId, packageName)) {
+            return null;
+        }
+
+        return association;
+    }
+
+    private Set<AssociationInfo> getAllAssociations() {
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            final Set<AssociationInfo> result = new ArraySet<>();
+            for (UserInfo user : mUserManager.getAliveUsers()) {
+                result.addAll(getAllAssociationsForUser(user.id));
+            }
+            return result;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
     void maybeGrantAutoRevokeExemptions() {
         Slog.d(LOG_TAG, "maybeGrantAutoRevokeExemptions()");
         PackageManager pm = getContext().getPackageManager();
@@ -293,7 +363,7 @@
             }
 
             try {
-                Set<AssociationInfo> associations = getAllAssociations(userId);
+                Set<AssociationInfo> associations = getAllAssociationsForUser(userId);
                 if (associations == null) {
                     continue;
                 }
@@ -325,67 +395,92 @@
         }
 
         @Override
-        public void associate(
-                AssociationRequest request,
-                IFindDeviceCallback callback,
-                String callingPackage) throws RemoteException {
-            Slog.i(LOG_TAG, "associate(request = " + request + ", callback = " + callback
-                    + ", callingPackage = " + callingPackage + ")");
-            mAssociationRequestsProcessor.process(request, callback, callingPackage);
+        public void associate(AssociationRequest request, IAssociationRequestCallback callback,
+                String packageName, int userId) throws RemoteException {
+            Slog.i(LOG_TAG, "associate() "
+                    + "request=" + request + ", "
+                    + "package=u" + userId + "/" + packageName);
+            mAssociationRequestsProcessor.process(request, packageName, userId, callback);
         }
 
         @Override
-        public void stopScan(AssociationRequest request,
-                IFindDeviceCallback callback,
-                String callingPackage) {
-            Slog.i(LOG_TAG, "stopScan(request = " + request + ")");
-            mAssociationRequestsProcessor.stopScan(request, callback, callingPackage);
-        }
-
-        @Override
-        public List<String> getAssociations(String callingPackage, int userId)
-                throws RemoteException {
-            if (!callerCanManageCompanionDevices()) {
-                checkCallerIsSystemOr(callingPackage, userId);
-                checkUsesFeature(callingPackage, getCallingUserId());
-            }
-            return new ArrayList<>(map(
-                    getAllAssociations(userId, callingPackage),
-                    a -> a.getDeviceMacAddress()));
-        }
-
-        @Override
-        public List<AssociationInfo> getAssociationsForUser(int userId) {
-            if (!callerCanManageCompanionDevices()) {
-                throw new SecurityException("Caller must hold "
-                        + android.Manifest.permission.MANAGE_COMPANION_DEVICES);
+        public List<AssociationInfo> getAssociations(String packageName, int userId) {
+            final int callingUid = getCallingUserId();
+            if (!checkCallerCanManageAssociationsForPackage(getContext(), userId, packageName)) {
+                throw new SecurityException("Caller (uid=" + callingUid + ") does not have "
+                        + "permissions to get associations for u" + userId + "/" + packageName);
             }
 
-            return new ArrayList<>(getAllAssociations(userId, null /* packageFilter */));
-        }
+            if (!checkCallerCanManagerCompanionDevice(getContext())) {
+                // If the caller neither is system nor holds MANAGE_COMPANION_DEVICES: it needs to
+                // request the feature (also: the caller is the app itself).
+                checkUsesFeature(packageName, getCallingUserId());
+            }
 
-        //TODO also revoke notification access
-        @Override
-        public void disassociate(String deviceMacAddress, String callingPackage)
-                throws RemoteException {
-            checkNotNull(deviceMacAddress);
-            checkCallerIsSystemOr(callingPackage);
-            checkUsesFeature(callingPackage, getCallingUserId());
-            removeAssociation(getCallingUserId(), callingPackage, deviceMacAddress);
-        }
-
-        private boolean callerCanManageCompanionDevices() {
-            return getContext().checkCallingOrSelfPermission(
-                    android.Manifest.permission.MANAGE_COMPANION_DEVICES)
-                    == PERMISSION_GRANTED;
+            return new ArrayList<>(
+                    CompanionDeviceManagerService.this.getAssociations(userId, packageName));
         }
 
         @Override
-        public PendingIntent requestNotificationAccess(ComponentName component)
+        public List<AssociationInfo> getAllAssociationsForUser(int userId) throws RemoteException {
+            enforceCallerCanInteractWithUserId(getContext(), userId);
+            enforceCallerCanManagerCompanionDevice(getContext(), "getAllAssociationsForUser");
+
+            return new ArrayList<>(
+                    CompanionDeviceManagerService.this.getAllAssociationsForUser(userId));
+        }
+
+        @Override
+        public void addOnAssociationsChangedListener(IOnAssociationsChangedListener listener,
+                int userId) {
+            enforceCallerCanInteractWithUserId(getContext(), userId);
+            enforceCallerCanManagerCompanionDevice(getContext(),
+                    "addOnAssociationsChangedListener");
+
+            //TODO: Implement.
+        }
+
+        @Override
+        public void removeOnAssociationsChangedListener(IOnAssociationsChangedListener listener,
+                int userId) {
+            //TODO: Implement.
+        }
+
+        @Override
+        public void legacyDisassociate(String deviceMacAddress, String packageName, int userId) {
+            requireNonNull(deviceMacAddress);
+            requireNonNull(packageName);
+
+            final AssociationInfo association =
+                    getAssociationWithCallerChecks(userId, packageName, deviceMacAddress);
+            if (association == null) {
+                throw new IllegalArgumentException("Association does not exist "
+                        + "or the caller does not have permissions to manage it "
+                        + "(ie. it belongs ot a different package or a different user).");
+            }
+
+            disassociateInternal(userId, association.getId());
+        }
+
+        @Override
+        public void disassociate(int associationId) {
+            final AssociationInfo association = getAssociationWithCallerChecks(associationId);
+            if (association == null) {
+                throw new IllegalArgumentException("Association with ID " + associationId + " "
+                        + "does not exist "
+                        + "or belongs to a different package "
+                        + "or belongs to a different user");
+            }
+
+            disassociateInternal(association.getUserId(), associationId);
+        }
+
+        @Override
+        public PendingIntent requestNotificationAccess(ComponentName component, int userId)
                 throws RemoteException {
             String callingPackage = component.getPackageName();
             checkCanCallNotificationApi(callingPackage);
-            int userId = getCallingUserId();
+            //TODO: check userId.
             String packageTitle = BidiFormatter.getInstance().unicodeWrap(
                     getPackageInfo(callingPackage, userId)
                             .applicationInfo
@@ -425,7 +520,7 @@
         public boolean isDeviceAssociatedForWifiConnection(String packageName, String macAddress,
                 int userId) {
             getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.MANAGE_COMPANION_DEVICES, "isDeviceAssociated");
+                    MANAGE_COMPANION_DEVICES, "isDeviceAssociated");
 
             boolean bypassMacPermission = getContext().getPackageManager().checkPermission(
                     android.Manifest.permission.COMPANION_APPROVE_WIFI_CONNECTIONS, packageName)
@@ -434,23 +529,22 @@
                 return true;
             }
 
-            return any(
-                    getAllAssociations(userId, packageName),
-                    a -> Objects.equals(a.getDeviceMacAddress(), macAddress));
+            return any(CompanionDeviceManagerService.this.getAssociations(userId, packageName),
+                    a -> a.isLinkedTo(macAddress));
         }
 
         @Override
-        public void registerDevicePresenceListenerService(
-                String packageName, String deviceAddress)
-                throws RemoteException {
-            registerDevicePresenceListenerActive(packageName, deviceAddress, true);
+        public void registerDevicePresenceListenerService(String deviceAddress,
+                String callingPackage, int userId) throws RemoteException {
+            //TODO: take the userId into account.
+            registerDevicePresenceListenerActive(callingPackage, deviceAddress, true);
         }
 
         @Override
-        public void unregisterDevicePresenceListenerService(
-                String packageName, String deviceAddress)
-                throws RemoteException {
-            registerDevicePresenceListenerActive(packageName, deviceAddress, false);
+        public void unregisterDevicePresenceListenerService(String deviceAddress,
+                String callingPackage, int userId) throws RemoteException {
+            //TODO: take the userId into account.
+            registerDevicePresenceListenerActive(callingPackage, deviceAddress, false);
         }
 
         @Override
@@ -464,12 +558,12 @@
             getContext().enforceCallingOrSelfPermission(
                     android.Manifest.permission.REQUEST_OBSERVE_COMPANION_DEVICE_PRESENCE,
                     "[un]registerDevicePresenceListenerService");
-            checkCallerIsSystemOr(packageName);
+            final int userId = getCallingUserId();
+            enforceCallerIsSystemOr(userId, packageName);
 
-            int userId = getCallingUserId();
             Set<AssociationInfo> deviceAssociations = filter(
-                    getAllAssociations(userId, packageName),
-                    association -> deviceAddress.equals(association.getDeviceMacAddress()));
+                    CompanionDeviceManagerService.this.getAssociations(userId, packageName),
+                    a -> a.isLinkedTo(deviceAddress));
 
             if (deviceAssociations.isEmpty()) {
                 throw new RemoteException(new DeviceNotAssociatedException("App " + packageName
@@ -478,8 +572,8 @@
             }
 
             updateAssociations(associations -> map(associations, association -> {
-                if (Objects.equals(association.getPackageName(), packageName)
-                        && Objects.equals(association.getDeviceMacAddress(), deviceAddress)) {
+                if (association.belongsToPackage(userId, packageName)
+                        && association.isLinkedTo(deviceAddress)) {
                     association.setNotifyOnDeviceNearby(active);
                 }
                 return association;
@@ -503,29 +597,31 @@
             createAssociationInternal(userId, macAddress, packageName, null);
         }
 
-        private void checkCanCallNotificationApi(String callingPackage) throws RemoteException {
-            checkCallerIsSystemOr(callingPackage);
-            int userId = getCallingUserId();
-            checkState(!ArrayUtils.isEmpty(getAllAssociations(userId, callingPackage)),
+        private void checkCanCallNotificationApi(String callingPackage) {
+            final int userId = getCallingUserId();
+            enforceCallerIsSystemOr(userId, callingPackage);
+
+            checkState(!ArrayUtils.isEmpty(
+                    CompanionDeviceManagerService.this.getAssociations(userId, callingPackage)),
                     "App must have an association before calling this API");
             checkUsesFeature(callingPackage, userId);
         }
 
         @Override
-        public boolean canPairWithoutPrompt(
-                String packageName, String deviceMacAddress, int userId) {
-            return any(
-                    getAllAssociations(userId, packageName, deviceMacAddress),
-                    a -> System.currentTimeMillis() - a.getTimeApprovedMs()
-                            < PAIR_WITHOUT_PROMPT_WINDOW_MS);
+        public boolean canPairWithoutPrompt(String packageName, String macAddress, int userId) {
+            final AssociationInfo association = getAssociation(userId, packageName, macAddress);
+            if (association == null) {
+                return false;
+            }
+            return System.currentTimeMillis() - association.getTimeApprovedMs()
+                    < PAIR_WITHOUT_PROMPT_WINDOW_MS;
         }
 
         @Override
         public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
                 String[] args, ShellCallback callback, ResultReceiver resultReceiver)
                 throws RemoteException {
-            getContext().enforceCallingOrSelfPermission(
-                    android.Manifest.permission.MANAGE_COMPANION_DEVICES, null);
+            enforceCallerCanManagerCompanionDevice(getContext(), "onShellCommand");
             new CompanionDeviceShellCommand(CompanionDeviceManagerService.this)
                     .exec(this, in, out, err, args, callback, resultReceiver);
         }
@@ -575,55 +671,14 @@
         }
     }
 
-    void checkCallerIsSystemOr(String pkg) throws RemoteException {
-        checkCallerIsSystemOr(pkg, getCallingUserId());
-    }
-
-    private void checkCallerIsSystemOr(String pkg, int userId) throws RemoteException {
-        if (isCallerSystem()) {
-            return;
-        }
-
-        checkArgument(getCallingUserId() == userId,
-                "Must be called by either same user or system");
-        int callingUid = Binder.getCallingUid();
-        if (mAppOpsManager.checkPackage(callingUid, pkg) != AppOpsManager.MODE_ALLOWED) {
-            throw new SecurityException(pkg + " doesn't belong to uid " + callingUid);
-        }
-    }
-
-    static int getCallingUserId() {
-        return UserHandle.getUserId(Binder.getCallingUid());
-    }
-
-    private static boolean isCallerSystem() {
-        return Binder.getCallingUid() == Process.SYSTEM_UID;
-    }
-
-    void checkUsesFeature(String pkg, int userId) {
-        if (isCallerSystem()) {
-            // Drop the requirement for calls from system process
-            return;
-        }
-
-        FeatureInfo[] reqFeatures = getPackageInfo(pkg, userId).reqFeatures;
-        String requiredFeature = PackageManager.FEATURE_COMPANION_DEVICE_SETUP;
-        int numFeatures = ArrayUtils.size(reqFeatures);
-        for (int i = 0; i < numFeatures; i++) {
-            if (requiredFeature.equals(reqFeatures[i].name)) return;
-        }
-        throw new IllegalStateException("Must declare uses-feature "
-                + requiredFeature
-                + " in manifest to use this API");
-    }
-
     void createAssociationInternal(
             int userId, String deviceMacAddress, String packageName, String deviceProfile) {
         final AssociationInfo association = new AssociationInfo(
                 getNewAssociationIdForPackage(userId, packageName),
                 userId,
                 packageName,
-                Arrays.asList(new DeviceId(TYPE_MAC_ADDRESS, deviceMacAddress)),
+                MacAddress.fromString(deviceMacAddress),
+                null,
                 deviceProfile,
                 /* managedByCompanionApp */false,
                 /* notifyOnDeviceNearby */ false ,
@@ -648,8 +703,8 @@
 
             // First: collect all IDs currently in use for this user's Associations.
             final SparseBooleanArray usedIds = new SparseBooleanArray();
-            for (AssociationInfo it : getAllAssociations(userId)) {
-                usedIds.put(it.getAssociationId(), true);
+            for (AssociationInfo it : getAllAssociationsForUser(userId)) {
+                usedIds.put(it.getId(), true);
             }
 
             // Second: collect all IDs that have been previously used for this package (and user).
@@ -674,19 +729,29 @@
         }
     }
 
-    void removeAssociation(int userId, String packageName, String deviceMacAddress) {
-        updateAssociations(associations -> filterOut(associations, it -> {
-            final boolean match = it.belongsToPackage(userId, packageName)
-                    && Objects.equals(it.getDeviceMacAddress(), deviceMacAddress);
-            if (match) {
-                onAssociationPreRemove(it);
-                markIdAsPreviouslyUsedForPackage(it.getAssociationId(), userId, packageName);
-            }
-            return match;
-        }), userId);
+    //TODO also revoke notification access
+    void disassociateInternal(@UserIdInt int userId, int associationId) {
+        updateAssociations(associations ->
+                filterOut(associations, it -> {
+                    if (it.getId() != associationId) return false;
+
+                    onAssociationPreRemove(it);
+                    markIdAsPreviouslyUsedForPackage(
+                            it.getId(), it.getUserId(), it.getPackageName());
+                    return true;
+                }), userId);
+
         restartBleScan();
     }
 
+    void clearAssociationForPackage(@UserIdInt int userId, @NonNull String packageName) {
+        if (DEBUG) Slog.d(LOG_TAG, "clearAssociationForPackage() u" + userId + "/" + packageName);
+
+        mCompanionDevicePresenceController.unbindDevicePresenceListener(packageName, userId);
+        updateAssociations(set -> filterOut(set, it -> it.belongsToPackage(userId, packageName)),
+                userId);
+    }
+
     private void markIdAsPreviouslyUsedForPackage(
             int associationId, @UserIdInt int userId, @NonNull String packageName) {
         synchronized (mLock) {
@@ -707,32 +772,15 @@
         String deviceProfile = association.getDeviceProfile();
         if (deviceProfile != null) {
             AssociationInfo otherAssociationWithDeviceProfile = find(
-                    getAllAssociations(association.getUserId()),
+                    getAllAssociationsForUser(association.getUserId()),
                     a -> !a.equals(association) && deviceProfile.equals(a.getDeviceProfile()));
             if (otherAssociationWithDeviceProfile != null) {
                 Slog.i(LOG_TAG, "Not revoking " + deviceProfile
                         + " for " + association
                         + " - profile still present in " + otherAssociationWithDeviceProfile);
             } else {
-                final long identity = Binder.clearCallingIdentity();
-                try {
-                    mRoleManager.removeRoleHolderAsUser(
-                            association.getDeviceProfile(),
-                            association.getPackageName(),
-                            RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
-                            UserHandle.of(association.getUserId()),
-                            getContext().getMainExecutor(),
-                            success -> {
-                                if (!success) {
-                                    Slog.e(LOG_TAG, "Failed to revoke device profile role "
-                                            + association.getDeviceProfile()
-                                            + " to " + association.getPackageName()
-                                            + " for user " + association.getUserId());
-                                }
-                            });
-                } finally {
-                    Binder.restoreCallingIdentity(identity);
-                }
+                Binder.withCleanCallingIdentity(
+                        () -> removeRoleHolderForAssociation(getContext(), association));
             }
         }
     }
@@ -780,9 +828,9 @@
 
         exemptFromAutoRevoke(packageInfo.packageName, packageInfo.applicationInfo.uid);
 
-        if (!association.isManagedByCompanionApp()) {
-            if (mCurrentlyConnectedDevices.contains(association.getDeviceMacAddress())) {
-                grantDeviceProfile(association);
+        if (!association.isSelfManaged()) {
+            if (mCurrentlyConnectedDevices.contains(association.getDeviceMacAddressAsString())) {
+                addRoleHolderForAssociation(getContext(), association);
             }
 
             if (association.isNotifyOnDeviceNearby()) {
@@ -810,17 +858,10 @@
 
     @Nullable
     private PackageInfo getPackageInfo(String packageName, int userId) {
-        return Binder.withCleanCallingIdentity(PooledLambda.obtainSupplier((context, pkg, id) -> {
-            try {
-                return context.getPackageManager().getPackageInfoAsUser(
-                        pkg,
-                        PackageManager.GET_PERMISSIONS | PackageManager.GET_CONFIGURATIONS,
-                        id);
-            } catch (PackageManager.NameNotFoundException e) {
-                Slog.e(LOG_TAG, "Failed to get PackageInfo for package " + pkg, e);
-                return null;
-            }
-        }, getContext(), packageName, userId).recycleOnUse());
+        final int flags = PackageManager.GET_PERMISSIONS | PackageManager.GET_CONFIGURATIONS;
+        return Binder.withCleanCallingIdentity(
+                () -> getContext().getPackageManager()
+                        .getPackageInfoAsUser(packageName, flags , userId));
     }
 
     private void recordAssociation(AssociationInfo association, int userId) {
@@ -833,7 +874,7 @@
         synchronized (mLock) {
             if (DEBUG) Slog.d(LOG_TAG, "Updating Associations set...");
 
-            final Set<AssociationInfo> prevAssociations = getAllAssociations(userId);
+            final Set<AssociationInfo> prevAssociations = getAllAssociationsForUser(userId);
             if (DEBUG) Slog.d(LOG_TAG, "  > Before : " + prevAssociations + "...");
 
             final Set<AssociationInfo> updatedAssociations = update.apply(
@@ -871,15 +912,6 @@
         }
     }
 
-    @NonNull Set<AssociationInfo> getAllAssociations(int userId) {
-        synchronized (mLock) {
-            readPersistedStateForUserIfNeededLocked(userId);
-            // This returns non-null, because the readAssociationsInfoForUserIfNeededLocked() method
-            // we just called adds an empty set, if there was no previously saved data.
-            return mCachedAssociations.get(userId);
-        }
-    }
-
     @GuardedBy("mLock")
     private void readPersistedStateForUserIfNeededLocked(@UserIdInt int userId) {
         if (mCachedAssociations.get(userId) != null) return;
@@ -908,49 +940,20 @@
         }
     }
 
-    Set<AssociationInfo> getAllAssociations(int userId, @Nullable String packageFilter) {
-        return filter(
-                getAllAssociations(userId),
-                // Null filter == get all associations
-                a -> packageFilter == null || Objects.equals(packageFilter, a.getPackageName()));
-    }
-
-    private Set<AssociationInfo> getAllAssociations() {
-        final long identity = Binder.clearCallingIdentity();
-        try {
-            ArraySet<AssociationInfo> result = new ArraySet<>();
-            for (UserInfo user : mUserManager.getAliveUsers()) {
-                result.addAll(getAllAssociations(user.id));
-            }
-            return result;
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
-    }
-
-    private Set<AssociationInfo> getAllAssociations(
-            int userId, @Nullable String packageFilter, @Nullable String addressFilter) {
-        return filter(
-                getAllAssociations(userId),
-                // Null filter == get all associations
-                a -> (packageFilter == null || Objects.equals(packageFilter, a.getPackageName()))
-                        && (addressFilter == null
-                                || Objects.equals(addressFilter, a.getDeviceMacAddress())));
-    }
-
     void onDeviceConnected(String address) {
         Slog.d(LOG_TAG, "onDeviceConnected(address = " + address + ")");
 
         mCurrentlyConnectedDevices.add(address);
 
         for (UserInfo user : getAllUsers()) {
-            for (AssociationInfo association : getAllAssociations(user.id)) {
-                if (Objects.equals(address, association.getDeviceMacAddress())) {
+            for (AssociationInfo association : getAllAssociationsForUser(user.id)) {
+                if (association.isLinkedTo(address)) {
                     if (association.getDeviceProfile() != null) {
                         Slog.i(LOG_TAG, "Granting role " + association.getDeviceProfile()
                                 + " to " + association.getPackageName()
                                 + " due to device connected: " + association.getDeviceMacAddress());
-                        grantDeviceProfile(association);
+
+                        addRoleHolderForAssociation(getContext(), association);
                     }
                 }
             }
@@ -959,27 +962,6 @@
         onDeviceNearby(address);
     }
 
-    private void grantDeviceProfile(AssociationInfo association) {
-        Slog.i(LOG_TAG, "grantDeviceProfile(association = " + association + ")");
-
-        if (association.getDeviceProfile() != null) {
-            mRoleManager.addRoleHolderAsUser(
-                    association.getDeviceProfile(),
-                    association.getPackageName(),
-                    RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP,
-                    UserHandle.of(association.getUserId()),
-                    getContext().getMainExecutor(),
-                    success -> {
-                        if (!success) {
-                            Slog.e(LOG_TAG, "Failed to grant device profile role "
-                                    + association.getDeviceProfile()
-                                    + " to " + association.getPackageName()
-                                    + " for user " + association.getUserId());
-                        }
-                    });
-        }
-    }
-
     void onDeviceDisconnected(String address) {
         Slog.d(LOG_TAG, "onDeviceDisconnected(address = " + address + ")");
 
@@ -1113,8 +1095,8 @@
         Set<AssociationInfo> result = new ArraySet<>();
         for (int i = 0, size = aliveUsers.size(); i < size; i++) {
             UserInfo user = aliveUsers.get(i);
-            for (AssociationInfo association : getAllAssociations(user.id)) {
-                if (Objects.equals(association.getDeviceMacAddress(), deviceAddress)) {
+            for (AssociationInfo association : getAllAssociationsForUser(user.id)) {
+                if (association.isLinkedTo(deviceAddress)) {
                     result.add(association);
                 }
             }
@@ -1224,10 +1206,10 @@
         ArrayList<ScanFilter> result = new ArrayList<>();
         ArraySet<String> addressesSeen = new ArraySet<>();
         for (AssociationInfo association : getAllAssociations()) {
-            if (association.isManagedByCompanionApp()) {
+            if (association.isSelfManaged()) {
                 continue;
             }
-            String address = association.getDeviceMacAddress();
+            String address = association.getDeviceMacAddressAsString();
             if (addressesSeen.contains(address)) {
                 continue;
             }
@@ -1273,4 +1255,19 @@
         forEach(orig, (key, value) -> copy.put(key, new ArraySet<>(value)));
         return copy;
     }
+
+    void checkUsesFeature(@NonNull String pkg, @UserIdInt int userId) {
+        if (getCallingUserId() == SYSTEM_UID) return;
+
+        final FeatureInfo[] requestedFeatures = getPackageInfo(pkg, userId).reqFeatures;
+        if (requestedFeatures != null) {
+            for (int i = 0; i < requestedFeatures.length; i++) {
+                if (FEATURE_COMPANION_DEVICE_SETUP.equals(requestedFeatures[i].name)) return;
+            }
+        }
+
+        throw new IllegalStateException("Must declare uses-feature "
+                + FEATURE_COMPANION_DEVICE_SETUP
+                + " in manifest to use this API");
+    }
 }
diff --git a/services/companion/java/com/android/server/companion/CompanionDevicePresenceController.java b/services/companion/java/com/android/server/companion/CompanionDevicePresenceController.java
index a79db2c..3e00846 100644
--- a/services/companion/java/com/android/server/companion/CompanionDevicePresenceController.java
+++ b/services/companion/java/com/android/server/companion/CompanionDevicePresenceController.java
@@ -67,7 +67,7 @@
             Slog.i(LOG_TAG,
                     "Sending onDeviceAppeared to " + association.getPackageName() + ")");
             primaryConnector.run(
-                    service -> service.onDeviceAppeared(association.getDeviceMacAddress()));
+                    s -> s.onDeviceAppeared(association.getDeviceMacAddressAsString()));
         }
     }
 
@@ -78,7 +78,7 @@
             Slog.i(LOG_TAG,
                     "Sending onDeviceDisappeared to " + association.getPackageName() + ")");
             primaryConnector.run(
-                    service -> service.onDeviceDisappeared(association.getDeviceMacAddress()));
+                    s -> s.onDeviceDisappeared(association.getDeviceMacAddressAsString()));
         }
     }
 
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
index e143f5e..3efbffc 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceShellCommand.java
@@ -19,6 +19,7 @@
 import static com.android.internal.util.CollectionUtils.forEach;
 import static com.android.server.companion.CompanionDeviceManagerService.LOG_TAG;
 
+import android.companion.AssociationInfo;
 import android.util.Log;
 import android.util.Slog;
 
@@ -37,7 +38,7 @@
             switch (cmd) {
                 case "list": {
                     forEach(
-                            mService.getAllAssociations(getNextArgInt()),
+                            mService.getAllAssociationsForUser(getNextArgInt()),
                             a -> getOutPrintWriter()
                                     .println(a.getPackageName() + " "
                                             + a.getDeviceMacAddress()));
@@ -53,8 +54,14 @@
                 break;
 
                 case "disassociate": {
-                    mService.removeAssociation(getNextArgInt(), getNextArgRequired(),
-                            getNextArgRequired());
+                    final int userId = getNextArgInt();
+                    final String packageName = getNextArgRequired();
+                    final String address = getNextArgRequired();
+                    final AssociationInfo association =
+                            mService.getAssociationWithCallerChecks(userId, packageName, address);
+                    if (association != null) {
+                        mService.disassociateInternal(userId, association.getId());
+                    }
                 }
                 break;
 
diff --git a/services/companion/java/com/android/server/companion/PermissionsUtils.java b/services/companion/java/com/android/server/companion/PermissionsUtils.java
new file mode 100644
index 0000000..a84bfa51
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/PermissionsUtils.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2021 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.companion;
+
+import static android.Manifest.permission.INTERACT_ACROSS_USERS;
+import static android.Manifest.permission.MANAGE_COMPANION_DEVICES;
+import static android.Manifest.permission.REQUEST_COMPANION_SELF_MANAGED;
+import static android.app.AppOpsManager.MODE_ALLOWED;
+import static android.companion.AssociationRequest.DEVICE_PROFILE_APP_STREAMING;
+import static android.companion.AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION;
+import static android.companion.AssociationRequest.DEVICE_PROFILE_WATCH;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.Binder.getCallingUid;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.UserHandle.getCallingUserId;
+
+import static java.util.Collections.unmodifiableMap;
+
+import android.Manifest;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.companion.CompanionDeviceManager;
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.ArrayMap;
+
+import com.android.internal.app.IAppOpsService;
+
+import java.util.Map;
+
+/**
+ * Utility methods for checking permissions required for accessing {@link CompanionDeviceManager}
+ * APIs (such as {@link Manifest.permission#REQUEST_COMPANION_PROFILE_WATCH},
+ * {@link Manifest.permission#REQUEST_COMPANION_PROFILE_APP_STREAMING},
+ * {@link Manifest.permission#REQUEST_COMPANION_SELF_MANAGED} etc.)
+ */
+final class PermissionsUtils {
+
+    private static final Map<String, String> DEVICE_PROFILE_TO_PERMISSION;
+    static {
+        final Map<String, String> map = new ArrayMap<>();
+        map.put(DEVICE_PROFILE_WATCH, Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH);
+        map.put(DEVICE_PROFILE_APP_STREAMING,
+                Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING);
+        map.put(DEVICE_PROFILE_AUTOMOTIVE_PROJECTION,
+                Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION);
+
+        DEVICE_PROFILE_TO_PERMISSION = unmodifiableMap(map);
+    }
+
+    static void enforceRequestDeviceProfilePermissions(
+            @NonNull Context context, @Nullable String deviceProfile) {
+        // Device profile can be null.
+        if (deviceProfile == null) return;
+
+        if (!DEVICE_PROFILE_TO_PERMISSION.containsKey(deviceProfile)) {
+            throw new IllegalArgumentException("Unsupported device profile: " + deviceProfile);
+        }
+
+        if (DEVICE_PROFILE_APP_STREAMING.equals(deviceProfile)) {
+            // TODO: remove, when properly supporting this profile.
+            throw new UnsupportedOperationException(
+                    "DEVICE_PROFILE_APP_STREAMING is not fully supported yet.");
+        }
+
+        if (DEVICE_PROFILE_AUTOMOTIVE_PROJECTION.equals(deviceProfile)) {
+            // TODO: remove, when properly supporting this profile.
+            throw new UnsupportedOperationException(
+                    "DEVICE_PROFILE_AUTOMOTIVE_PROJECTION is not fully supported yet.");
+        }
+
+        final String permission = DEVICE_PROFILE_TO_PERMISSION.get(deviceProfile);
+        if (context.checkCallingOrSelfPermission(permission) != PERMISSION_GRANTED) {
+            throw new SecurityException("Application must hold " + permission + " to associate "
+                    + "with a device with " + deviceProfile + " profile.");
+        }
+    }
+
+    static void enforceRequestSelfManagedPermission(@NonNull Context context) {
+        if (context.checkCallingOrSelfPermission(REQUEST_COMPANION_SELF_MANAGED)
+                != PERMISSION_GRANTED) {
+            throw new SecurityException("Application does not hold "
+                    + REQUEST_COMPANION_SELF_MANAGED);
+        }
+    }
+
+    static boolean checkCallerCanInteractWithUserId(@NonNull Context context, int userId) {
+        if (getCallingUserId() == userId) return true;
+
+        return context.checkCallingPermission(INTERACT_ACROSS_USERS) == PERMISSION_GRANTED;
+    }
+
+    static void enforceCallerCanInteractWithUserId(@NonNull Context context, int userId) {
+        if (getCallingUserId() == userId) return;
+
+        context.enforceCallingPermission(INTERACT_ACROSS_USERS, null);
+    }
+
+    static boolean checkCallerIsSystemOr(@UserIdInt int userId, @NonNull String packageName) {
+        final int callingUid = getCallingUid();
+        if (callingUid == SYSTEM_UID) return true;
+
+        if (getCallingUserId() != userId) return false;
+
+        if (!checkPackage(callingUid, packageName)) return false;
+
+        return true;
+    }
+
+    static void enforceCallerIsSystemOr(@UserIdInt int userId, @NonNull String packageName) {
+        final int callingUid = getCallingUid();
+        if (callingUid == SYSTEM_UID) return;
+
+        final int callingUserId = getCallingUserId();
+        if (getCallingUserId() != userId) {
+            throw new SecurityException("Calling UserId (" + callingUserId + ") does not match "
+                    + "the expected UserId (" + userId + ")");
+        }
+
+        if (!checkPackage(callingUid, packageName)) {
+            throw new SecurityException(packageName + " doesn't belong to calling uid ("
+                    + callingUid + ")");
+        }
+    }
+
+    static boolean checkCallerCanManagerCompanionDevice(@NonNull Context context) {
+        if (getCallingUserId() == SYSTEM_UID) return true;
+
+        return context.checkCallingPermission(MANAGE_COMPANION_DEVICES) == PERMISSION_GRANTED;
+    }
+
+    static void enforceCallerCanManagerCompanionDevice(@NonNull Context context,
+            @Nullable String message) {
+        if (getCallingUserId() == SYSTEM_UID) return;
+
+        context.enforceCallingPermission(MANAGE_COMPANION_DEVICES, message);
+    }
+
+    static boolean checkCallerCanManageAssociationsForPackage(@NonNull Context context,
+            @UserIdInt int userId, @NonNull String packageName) {
+        if (checkCallerIsSystemOr(userId, packageName)) return true;
+
+        if (!checkCallerCanInteractWithUserId(context, userId)) return false;
+
+        return checkCallerCanManagerCompanionDevice(context);
+    }
+
+    private static boolean checkPackage(@UserIdInt int uid, @NonNull String packageName) {
+        try {
+            return getAppOpsService().checkPackage(uid, packageName) == MODE_ALLOWED;
+        } catch (RemoteException e) {
+            // Can't happen: AppOpsManager is running in the same process.
+            return true;
+        }
+    }
+
+    private static IAppOpsService getAppOpsService() {
+        if (sAppOpsService == null) {
+            synchronized (PermissionsUtils.class) {
+                if (sAppOpsService == null) {
+                    sAppOpsService = IAppOpsService.Stub.asInterface(
+                            ServiceManager.getService(Context.APP_OPS_SERVICE));
+                }
+            }
+        }
+        return sAppOpsService;
+    }
+
+    // DO NOT USE DIRECTLY! Access via getAppOpsService().
+    private static IAppOpsService sAppOpsService = null;
+
+    private PermissionsUtils() {}
+}
diff --git a/services/companion/java/com/android/server/companion/PersistentDataStore.java b/services/companion/java/com/android/server/companion/PersistentDataStore.java
index 5b8d7e5..87558df 100644
--- a/services/companion/java/com/android/server/companion/PersistentDataStore.java
+++ b/services/companion/java/com/android/server/companion/PersistentDataStore.java
@@ -16,8 +16,6 @@
 
 package com.android.server.companion;
 
-import static android.companion.DeviceId.TYPE_MAC_ADDRESS;
-
 import static com.android.internal.util.CollectionUtils.forEach;
 import static com.android.internal.util.XmlUtils.readBooleanAttribute;
 import static com.android.internal.util.XmlUtils.readIntAttribute;
@@ -35,7 +33,7 @@
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.companion.AssociationInfo;
-import android.companion.DeviceId;
+import android.net.MacAddress;
 import android.os.Environment;
 import android.util.AtomicFile;
 import android.util.ExceptionUtils;
@@ -53,10 +51,7 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -101,8 +96,8 @@
  * Since Android T the data is stored using the v1 schema.
  * In the v1 schema, a list of the previously used IDs is storead along with the association
  * records.
- * In the v1 schema, we no longer store MAC addresses, instead each assocition record may have a
- * number of DeviceIds.
+ * V1 schema adds a new optional `display_name` attribute, and makes the `mac_address` attribute
+ * optional.
  *
  * @see #CURRENT_PERSISTENCE_VERSION
  * @see #readAssociationsV1(TypedXmlPullParser, int, Set)
@@ -116,21 +111,19 @@
  *         <association
  *             id="1"
  *             package="com.sample.companion.app"
- *             managed_by_app="false"
+ *             mac_address="AA:BB:CC:DD:EE:00"
+ *             self_managed="false"
  *             notify_device_nearby="false"
- *             time_approved="1634389553216">
- *             <device-id type="mac_address" value="AA:BB:CC:DD:EE:00" />
- *         </association>
+ *             time_approved="1634389553216"/>
  *
  *         <association
  *             id="3"
  *             profile="android.app.role.COMPANION_DEVICE_WATCH"
  *             package="com.sample.companion.another.app"
- *             managed_by_app="false"
+ *             display_name="Jhon's Chromebook"
+ *             self_managed="true"
  *             notify_device_nearby="false"
- *             time_approved="1634641160229">
- *             <device-id type="mac_address" value="AA:BB:CC:DD:EE:FF" />
- *         </association>
+ *             time_approved="1634641160229"/>
  *     </associations>
  *
  *     <previously-used-ids>
@@ -153,7 +146,6 @@
     private static final String XML_TAG_STATE = "state";
     private static final String XML_TAG_ASSOCIATIONS = "associations";
     private static final String XML_TAG_ASSOCIATION = "association";
-    private static final String XML_TAG_DEVICE_ID = "device-id";
     private static final String XML_TAG_PREVIOUSLY_USED_IDS = "previously-used-ids";
     private static final String XML_TAG_PACKAGE = "package";
     private static final String XML_TAG_ID = "id";
@@ -164,13 +156,14 @@
     private static final String XML_ATTR_PACKAGE_NAME = "package_name";
     // Used in <association> elements, nested within <associations> elements.
     private static final String XML_ATTR_PACKAGE = "package";
-    private static final String XML_ATTR_DEVICE = "device";
+    private static final String XML_ATTR_MAC_ADDRESS = "mac_address";
+    private static final String XML_ATTR_DISPLAY_NAME = "display_name";
     private static final String XML_ATTR_PROFILE = "profile";
-    private static final String XML_ATTR_MANAGED_BY_APP = "managed_by_app";
+    private static final String XML_ATTR_SELF_MANAGED = "self_managed";
     private static final String XML_ATTR_NOTIFY_DEVICE_NEARBY = "notify_device_nearby";
     private static final String XML_ATTR_TIME_APPROVED = "time_approved";
-    private static final String XML_ATTR_TYPE = "type";
-    private static final String XML_ATTR_VALUE = "value";
+
+    private static final String LEGACY_XML_ATTR_DEVICE = "device";
 
     private final @NonNull ConcurrentMap<Integer, AtomicFile> mUserIdToStorageFile =
             new ConcurrentHashMap<>();
@@ -353,9 +346,7 @@
         requireStartOfTag(parser, XML_TAG_ASSOCIATION);
 
         final String appPackage = readStringAttribute(parser, XML_ATTR_PACKAGE);
-        // In v0, CDM did not have a notion of a DeviceId yet, instead each Association had a MAC
-        // address.
-        final String deviceAddress = readStringAttribute(parser, XML_ATTR_DEVICE);
+        final String deviceAddress = readStringAttribute(parser, LEGACY_XML_ATTR_DEVICE);
 
         if (appPackage == null || deviceAddress == null) return;
 
@@ -363,10 +354,8 @@
         final boolean notify = readBooleanAttribute(parser, XML_ATTR_NOTIFY_DEVICE_NEARBY);
         final long timeApproved = readLongAttribute(parser, XML_ATTR_TIME_APPROVED, 0L);
 
-        // "Convert" MAC address into a DeviceId.
-        final List<DeviceId> deviceIds = Arrays.asList(
-                new DeviceId(TYPE_MAC_ADDRESS, deviceAddress));
-        out.add(new AssociationInfo(associationId, userId, appPackage, deviceIds, profile,
+        out.add(new AssociationInfo(associationId, userId, appPackage,
+                MacAddress.fromString(deviceAddress), null, profile,
                 /* managedByCompanionApp */false, notify, timeApproved));
     }
 
@@ -391,23 +380,18 @@
         final int associationId = readIntAttribute(parser, XML_ATTR_ID);
         final String profile = readStringAttribute(parser, XML_ATTR_PROFILE);
         final String appPackage = readStringAttribute(parser, XML_ATTR_PACKAGE);
-        final boolean managedByApp = readBooleanAttribute(parser, XML_ATTR_MANAGED_BY_APP);
+        final MacAddress macAddress = stringToMacAddress(
+                readStringAttribute(parser, XML_ATTR_MAC_ADDRESS));
+        final String displayName = readStringAttribute(parser, XML_ATTR_DISPLAY_NAME);
+        final boolean selfManaged = readBooleanAttribute(parser, XML_ATTR_SELF_MANAGED);
         final boolean notify = readBooleanAttribute(parser, XML_ATTR_NOTIFY_DEVICE_NEARBY);
         final long timeApproved = readLongAttribute(parser, XML_ATTR_TIME_APPROVED, 0L);
 
-        final List<DeviceId> deviceIds = new ArrayList<>();
-        while (true) {
-            parser.nextTag();
-            if (isEndOfTag(parser, XML_TAG_ASSOCIATION)) break;
-            if (!isStartOfTag(parser, XML_TAG_DEVICE_ID)) continue;
-
-            final String type = readStringAttribute(parser, XML_ATTR_TYPE);
-            final String value = readStringAttribute(parser, XML_ATTR_VALUE);
-            deviceIds.add(new DeviceId(type, value));
+        final AssociationInfo associationInfo = createAssociationInfoNoThrow(associationId, userId,
+                appPackage, macAddress, displayName, profile, selfManaged, notify, timeApproved);
+        if (associationInfo != null) {
+            out.add(associationInfo);
         }
-
-        out.add(new AssociationInfo(associationId, userId, appPackage, deviceIds, profile,
-                managedByApp, notify, timeApproved));
     }
 
     private static void readPreviouslyUsedIdsV1(@NonNull TypedXmlPullParser parser,
@@ -447,32 +431,19 @@
             throws IOException {
         final XmlSerializer serializer = parent.startTag(null, XML_TAG_ASSOCIATION);
 
-        writeIntAttribute(serializer, XML_ATTR_ID, a.getAssociationId());
+        writeIntAttribute(serializer, XML_ATTR_ID, a.getId());
         writeStringAttribute(serializer, XML_ATTR_PROFILE, a.getDeviceProfile());
         writeStringAttribute(serializer, XML_ATTR_PACKAGE, a.getPackageName());
-        writeBooleanAttribute(serializer, XML_ATTR_MANAGED_BY_APP, a.isManagedByCompanionApp());
+        writeStringAttribute(serializer, XML_ATTR_MAC_ADDRESS, a.getDeviceMacAddressAsString());
+        writeStringAttribute(serializer, XML_ATTR_DISPLAY_NAME, a.getDisplayName());
+        writeBooleanAttribute(serializer, XML_ATTR_SELF_MANAGED, a.isSelfManaged());
         writeBooleanAttribute(
                 serializer, XML_ATTR_NOTIFY_DEVICE_NEARBY, a.isNotifyOnDeviceNearby());
         writeLongAttribute(serializer, XML_ATTR_TIME_APPROVED, a.getTimeApprovedMs());
 
-        final List<DeviceId> deviceIds = a.getDeviceIds();
-        for (int i = 0, size = deviceIds.size(); i < size; i++) {
-            writeDeviceId(serializer, deviceIds.get(i));
-        }
-
         serializer.endTag(null, XML_TAG_ASSOCIATION);
     }
 
-    private static void writeDeviceId(@NonNull XmlSerializer parent, @NonNull DeviceId deviceId)
-            throws IOException {
-        final XmlSerializer serializer = parent.startTag(null, XML_TAG_DEVICE_ID);
-
-        writeStringAttribute(serializer, XML_ATTR_TYPE, deviceId.getType());
-        writeStringAttribute(serializer, XML_ATTR_VALUE, deviceId.getValue());
-
-        serializer.endTag(null, XML_TAG_DEVICE_ID);
-    }
-
     private static void writePreviouslyUsedIds(@NonNull XmlSerializer parent,
             @NonNull Map<String, Set<Integer>> previouslyUsedIdsPerPackage) throws IOException {
         final XmlSerializer serializer = parent.startTag(null, XML_TAG_PREVIOUSLY_USED_IDS);
@@ -509,4 +480,22 @@
         throw new XmlPullParserException(
                 "Should be at the start of \"" + XML_TAG_ASSOCIATIONS + "\" tag");
     }
+
+    private static @Nullable MacAddress stringToMacAddress(@Nullable String address) {
+        return address != null ? MacAddress.fromString(address) : null;
+    }
+
+    private static AssociationInfo createAssociationInfoNoThrow(int associationId,
+            @UserIdInt int userId, @NonNull String appPackage, @Nullable MacAddress macAddress,
+            @Nullable CharSequence displayName, @Nullable String profile, boolean selfManaged,
+            boolean notify, long timeApproved) {
+        AssociationInfo associationInfo = null;
+        try {
+            associationInfo = new AssociationInfo(associationId, userId, appPackage, macAddress,
+                    displayName, profile, selfManaged, notify, timeApproved);
+        } catch (Exception e) {
+            if (DEBUG) Slog.w(LOG_TAG, "Could not create AssociationInfo", e);
+        }
+        return associationInfo;
+    }
 }
diff --git a/services/companion/java/com/android/server/companion/RolesUtils.java b/services/companion/java/com/android/server/companion/RolesUtils.java
new file mode 100644
index 0000000..76340fc
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/RolesUtils.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2021 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.companion;
+
+import static android.app.role.RoleManager.MANAGE_HOLDERS_FLAG_DONT_KILL_APP;
+
+import static com.android.server.companion.CompanionDeviceManagerService.DEBUG;
+import static com.android.server.companion.CompanionDeviceManagerService.LOG_TAG;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.app.role.RoleManager;
+import android.companion.AssociationInfo;
+import android.content.Context;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import java.util.List;
+
+/** Utility methods for accessing {@link RoleManager} APIs. */
+final class RolesUtils {
+
+    static boolean isRoleHolder(@NonNull Context context, @UserIdInt int userId,
+            @NonNull String packageName, @NonNull String role) {
+        final RoleManager roleManager = context.getSystemService(RoleManager.class);
+        final List<String> roleHolders = roleManager.getRoleHoldersAsUser(
+                role, UserHandle.of(userId));
+        return roleHolders.contains(packageName);
+    }
+
+    static void addRoleHolderForAssociation(
+            @NonNull Context context, @NonNull AssociationInfo associationInfo) {
+        if (DEBUG) {
+            Slog.d(LOG_TAG, "addRoleHolderForAssociation() associationInfo=" + associationInfo);
+        }
+
+        final String deviceProfile = associationInfo.getDeviceProfile();
+        if (deviceProfile == null) return;
+
+        final RoleManager roleManager = context.getSystemService(RoleManager.class);
+
+        final String packageName = associationInfo.getPackageName();
+        final int userId = associationInfo.getUserId();
+        final UserHandle userHandle = UserHandle.of(userId);
+
+        roleManager.addRoleHolderAsUser(deviceProfile, packageName,
+                MANAGE_HOLDERS_FLAG_DONT_KILL_APP, userHandle, context.getMainExecutor(),
+                success -> {
+                    if (!success) {
+                        Slog.e(LOG_TAG, "Failed to add u" + userId + "\\" + packageName
+                                + " to the list of " + deviceProfile + " holders.");
+                    }
+                });
+    }
+
+    static void removeRoleHolderForAssociation(
+            @NonNull Context context, @NonNull AssociationInfo associationInfo) {
+        if (DEBUG) {
+            Slog.d(LOG_TAG, "removeRoleHolderForAssociation() associationInfo=" + associationInfo);
+        }
+
+        final String deviceProfile = associationInfo.getDeviceProfile();
+        if (deviceProfile == null) return;
+
+        final RoleManager roleManager = context.getSystemService(RoleManager.class);
+
+        final String packageName = associationInfo.getPackageName();
+        final int userId = associationInfo.getUserId();
+        final UserHandle userHandle = UserHandle.of(userId);
+
+        roleManager.removeRoleHolderAsUser(deviceProfile, packageName,
+                MANAGE_HOLDERS_FLAG_DONT_KILL_APP, userHandle, context.getMainExecutor(),
+                success -> {
+                    if (!success) {
+                        Slog.e(LOG_TAG, "Failed to remove u" + userId + "\\" + packageName
+                                + " from the list of " + deviceProfile + " holders.");
+                    }
+                });
+    }
+
+    private RolesUtils() {};
+}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 9f22489..9351415 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -137,6 +137,7 @@
     ],
 
     required: [
+        "default_television.xml",
         "gps_debug.conf",
         "protolog.conf.json.gz",
     ],
diff --git a/services/core/java/com/android/server/AppFuseMountException.java b/services/core/java/com/android/server/AppFuseMountException.java
new file mode 100644
index 0000000..9a9379e
--- /dev/null
+++ b/services/core/java/com/android/server/AppFuseMountException.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 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;
+
+import android.os.Parcel;
+
+/**
+ * An exception that indicates there was an error with a
+ * app fuse mount operation.
+ */
+public class AppFuseMountException extends Exception {
+    public AppFuseMountException(String detailMessage) {
+        super(detailMessage);
+    }
+
+    public AppFuseMountException(String detailMessage, Throwable throwable) {
+        super(detailMessage, throwable);
+    }
+
+    /**
+     * Rethrow as a {@link RuntimeException} subclass that is handled by
+     * {@link Parcel#writeException(Exception)}.
+     */
+    public IllegalArgumentException rethrowAsParcelableException() {
+        throw new IllegalStateException(getMessage(), this);
+    }
+}
diff --git a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
index 197321f..263ff18 100644
--- a/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
+++ b/services/core/java/com/android/server/BluetoothAirplaneModeListener.java
@@ -35,6 +35,7 @@
  * when Bluetooth is on and Bluetooth is in one of the following situations:
  *   1. Bluetooth A2DP is connected.
  *   2. Bluetooth Hearing Aid profile is connected.
+ *   3. Bluetooth LE Audio is connected
  */
 class BluetoothAirplaneModeListener {
     private static final String TAG = "BluetoothAirplaneModeListener";
@@ -132,7 +133,7 @@
             return false;
         }
         if (!mAirplaneHelper.isBluetoothOn() || !mAirplaneHelper.isAirplaneModeOn()
-                || !mAirplaneHelper.isA2dpOrHearingAidConnected()) {
+                || !mAirplaneHelper.isMediaProfileConnected()) {
             return false;
         }
         return true;
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index f62935a..8860a81 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -35,6 +35,7 @@
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothProtoEnums;
 import android.bluetooth.IBluetooth;
@@ -456,12 +457,13 @@
                     }
                 }
             } else if (BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED.equals(action)
-                    || BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
+                    || BluetoothHearingAid.ACTION_CONNECTION_STATE_CHANGED.equals(action)
+                    || BluetoothLeAudio.ACTION_LE_AUDIO_CONNECTION_STATE_CHANGED.equals(action)) {
                 final int state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                         BluetoothProfile.STATE_CONNECTED);
                 if (mHandler.hasMessages(MESSAGE_INIT_FLAGS_CHANGED)
                         && state == BluetoothProfile.STATE_DISCONNECTED
-                        && !mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) {
+                        && !mBluetoothModeChangeHelper.isMediaProfileConnected()) {
                     Slog.i(TAG, "Device disconnected, reactivating pending flag changes");
                     onInitFlagsChanged();
                 }
@@ -2291,7 +2293,7 @@
                         Slog.d(TAG, "MESSAGE_INIT_FLAGS_CHANGED");
                     }
                     mHandler.removeMessages(MESSAGE_INIT_FLAGS_CHANGED);
-                    if (mBluetoothModeChangeHelper.isA2dpOrHearingAidConnected()) {
+                    if (mBluetoothModeChangeHelper.isMediaProfileConnected()) {
                         Slog.i(TAG, "Delaying MESSAGE_INIT_FLAGS_CHANGED by "
                                 + DELAY_FOR_RETRY_INIT_FLAG_CHECK_MS
                                 + " ms due to existing connections");
diff --git a/services/core/java/com/android/server/BluetoothModeChangeHelper.java b/services/core/java/com/android/server/BluetoothModeChangeHelper.java
index 3642e4d..e5854c9 100644
--- a/services/core/java/com/android/server/BluetoothModeChangeHelper.java
+++ b/services/core/java/com/android/server/BluetoothModeChangeHelper.java
@@ -20,6 +20,7 @@
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothHearingAid;
+import android.bluetooth.BluetoothLeAudio;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.BluetoothProfile.ServiceListener;
 import android.content.Context;
@@ -37,6 +38,7 @@
 public class BluetoothModeChangeHelper {
     private volatile BluetoothA2dp mA2dp;
     private volatile BluetoothHearingAid mHearingAid;
+    private volatile BluetoothLeAudio mLeAudio;
     private final BluetoothAdapter mAdapter;
     private final Context mContext;
 
@@ -47,6 +49,7 @@
         mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.A2DP);
         mAdapter.getProfileProxy(mContext, mProfileServiceListener,
                 BluetoothProfile.HEARING_AID);
+        mAdapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.LE_AUDIO);
     }
 
     private final ServiceListener mProfileServiceListener = new ServiceListener() {
@@ -60,6 +63,9 @@
                 case BluetoothProfile.HEARING_AID:
                     mHearingAid = (BluetoothHearingAid) proxy;
                     break;
+                case BluetoothProfile.LE_AUDIO:
+                    mLeAudio = (BluetoothLeAudio) proxy;
+                    break;
                 default:
                     break;
             }
@@ -75,6 +81,9 @@
                 case BluetoothProfile.HEARING_AID:
                     mHearingAid = null;
                     break;
+                case BluetoothProfile.LE_AUDIO:
+                    mLeAudio = null;
+                    break;
                 default:
                     break;
             }
@@ -82,8 +91,8 @@
     };
 
     @VisibleForTesting
-    public boolean isA2dpOrHearingAidConnected() {
-        return isA2dpConnected() || isHearingAidConnected();
+    public boolean isMediaProfileConnected() {
+        return isA2dpConnected() || isHearingAidConnected() || isLeAudioConnected();
     }
 
     @VisibleForTesting
@@ -142,4 +151,12 @@
         }
         return hearingAid.getConnectedDevices().size() > 0;
     }
+
+    private boolean isLeAudioConnected() {
+        final BluetoothLeAudio leAudio = mLeAudio;
+        if (leAudio == null) {
+            return false;
+        }
+        return leAudio.getConnectedDevices().size() > 0;
+    }
 }
diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java
index b2f5396..513d86e7 100644
--- a/services/core/java/com/android/server/MasterClearReceiver.java
+++ b/services/core/java/com/android/server/MasterClearReceiver.java
@@ -181,7 +181,7 @@
         public WipeDataTask(Context context, Thread chainedTask) {
             mContext = context;
             mChainedTask = chainedTask;
-            mProgressDialog = new ProgressDialog(context);
+            mProgressDialog = new ProgressDialog(context, R.style.Theme_DeviceDefault_System);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index c7e9068..a2c2dbd 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -39,8 +39,6 @@
 import static android.net.NetworkStats.TAG_NONE;
 import static android.net.TrafficStats.UID_TETHERING;
 
-import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
-
 import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.content.Context;
@@ -72,7 +70,6 @@
 import android.os.ServiceSpecificException;
 import android.os.StrictMode;
 import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.Trace;
 import android.text.TextUtils;
 import android.util.Log;
@@ -446,9 +443,6 @@
         // push any existing quota or UID rules
         synchronized (mQuotaLock) {
 
-            // Netd unconditionally enable bandwidth control
-            SystemProperties.set(PROP_QTAGUID_ENABLED, "1");
-
             mStrictEnabled = true;
 
             setDataSaverModeEnabled(mDataSaverMode);
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index c9608a5..3e02084 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2021 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.
@@ -20,24 +20,27 @@
 import android.content.Context;
 import android.content.Intent;
 import android.database.ContentObserver;
-import android.net.NetworkStack;
 import android.net.Uri;
 import android.net.nsd.INsdManager;
+import android.net.nsd.INsdManagerCallback;
+import android.net.nsd.INsdServiceConnector;
 import android.net.nsd.NsdManager;
 import android.net.nsd.NsdServiceInfo;
 import android.os.Handler;
 import android.os.HandlerThread;
+import android.os.IBinder;
 import android.os.Message;
-import android.os.Messenger;
+import android.os.RemoteException;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.util.Base64;
+import android.util.Log;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseIntArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
@@ -72,12 +75,11 @@
     /**
      * Clients receiving asynchronous messages
      */
-    private final HashMap<Messenger, ClientInfo> mClients = new HashMap<>();
+    private final HashMap<NsdServiceConnector, ClientInfo> mClients = new HashMap<>();
 
     /* A map from unique id to client info */
     private final SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<>();
 
-    private final AsyncChannel mReplyChannel = new AsyncChannel();
     private final long mCleanupDelayMs;
 
     private static final int INVALID_ID = 0;
@@ -149,65 +151,66 @@
         class DefaultState extends State {
             @Override
             public boolean processMessage(Message msg) {
-                ClientInfo cInfo = null;
+                final ClientInfo cInfo;
+                final int clientId = msg.arg2;
                 switch (msg.what) {
-                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
-                        if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
-                            AsyncChannel c = (AsyncChannel) msg.obj;
-                            if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
-                            c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);
-                            cInfo = new ClientInfo(c, msg.replyTo);
-                            mClients.put(msg.replyTo, cInfo);
-                        } else {
-                            Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
+                    case NsdManager.REGISTER_CLIENT:
+                        final Pair<NsdServiceConnector, INsdManagerCallback> arg =
+                                (Pair<NsdServiceConnector, INsdManagerCallback>) msg.obj;
+                        final INsdManagerCallback cb = arg.second;
+                        try {
+                            cb.asBinder().linkToDeath(arg.first, 0);
+                            cInfo = new ClientInfo(cb);
+                            mClients.put(arg.first, cInfo);
+                        } catch (RemoteException e) {
+                            Log.w(TAG, "Client " + clientId + " has already died");
                         }
                         break;
-                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
-                        switch (msg.arg1) {
-                            case AsyncChannel.STATUS_SEND_UNSUCCESSFUL:
-                                Slog.e(TAG, "Send failed, client connection lost");
-                                break;
-                            case AsyncChannel.STATUS_REMOTE_DISCONNECTION:
-                                if (DBG) Slog.d(TAG, "Client disconnected");
-                                break;
-                            default:
-                                if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
-                                break;
-                        }
-
-                        cInfo = mClients.get(msg.replyTo);
+                    case NsdManager.UNREGISTER_CLIENT:
+                        final NsdServiceConnector connector = (NsdServiceConnector) msg.obj;
+                        cInfo = mClients.remove(connector);
                         if (cInfo != null) {
                             cInfo.expungeAllRequests();
-                            mClients.remove(msg.replyTo);
                             if (cInfo.isLegacy()) {
                                 mLegacyClientCount -= 1;
                             }
                         }
                         maybeScheduleStop();
                         break;
-                    case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
-                        AsyncChannel ac = new AsyncChannel();
-                        ac.connect(mContext, getHandler(), msg.replyTo);
-                        break;
                     case NsdManager.DISCOVER_SERVICES:
-                        replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
-                                NsdManager.FAILURE_INTERNAL_ERROR);
+                        cInfo = getClientInfoForReply(msg);
+                        if (cInfo != null) {
+                            cInfo.onDiscoverServicesFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                        }
                        break;
                     case NsdManager.STOP_DISCOVERY:
-                       replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
-                               NsdManager.FAILURE_INTERNAL_ERROR);
+                        cInfo = getClientInfoForReply(msg);
+                        if (cInfo != null) {
+                            cInfo.onStopDiscoveryFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                        }
                         break;
                     case NsdManager.REGISTER_SERVICE:
-                        replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
-                                NsdManager.FAILURE_INTERNAL_ERROR);
+                        cInfo = getClientInfoForReply(msg);
+                        if (cInfo != null) {
+                            cInfo.onRegisterServiceFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                        }
                         break;
                     case NsdManager.UNREGISTER_SERVICE:
-                        replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
-                                NsdManager.FAILURE_INTERNAL_ERROR);
+                        cInfo = getClientInfoForReply(msg);
+                        if (cInfo != null) {
+                            cInfo.onUnregisterServiceFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                        }
                         break;
                     case NsdManager.RESOLVE_SERVICE:
-                        replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
-                                NsdManager.FAILURE_INTERNAL_ERROR);
+                        cInfo = getClientInfoForReply(msg);
+                        if (cInfo != null) {
+                            cInfo.onResolveServiceFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
+                        }
                         break;
                     case NsdManager.DAEMON_CLEANUP:
                         mDaemon.maybeStop();
@@ -215,7 +218,7 @@
                     // This event should be only sent by the legacy (target SDK < S) clients.
                     // Mark the sending client as legacy.
                     case NsdManager.DAEMON_STARTUP:
-                        cInfo = mClients.get(msg.replyTo);
+                        cInfo = getClientInfoForReply(msg);
                         if (cInfo != null) {
                             cancelStop();
                             cInfo.setLegacy();
@@ -230,6 +233,11 @@
                 }
                 return HANDLED;
             }
+
+            private ClientInfo getClientInfoForReply(Message msg) {
+                final ListenerArgs args = (ListenerArgs) msg.obj;
+                return mClients.get(args.connector);
+            }
         }
 
         class DisabledState extends State {
@@ -289,122 +297,119 @@
 
             @Override
             public boolean processMessage(Message msg) {
-                ClientInfo clientInfo;
-                NsdServiceInfo servInfo;
-                int id;
+                final ClientInfo clientInfo;
+                final int id;
+                final int clientId = msg.arg2;
+                final ListenerArgs args;
                 switch (msg.what) {
-                    case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
-                        return NOT_HANDLED;
-                    case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
-                        return NOT_HANDLED;
                     case NsdManager.DISABLE:
                         //TODO: cleanup clients
                         transitionTo(mDisabledState);
                         break;
                     case NsdManager.DISCOVER_SERVICES:
                         if (DBG) Slog.d(TAG, "Discover services");
-                        servInfo = (NsdServiceInfo) msg.obj;
-                        clientInfo = mClients.get(msg.replyTo);
+                        args = (ListenerArgs) msg.obj;
+                        clientInfo = mClients.get(args.connector);
 
                         if (requestLimitReached(clientInfo)) {
-                            replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
-                                    NsdManager.FAILURE_MAX_LIMIT);
+                            clientInfo.onDiscoverServicesFailed(
+                                    clientId, NsdManager.FAILURE_MAX_LIMIT);
                             break;
                         }
 
                         maybeStartDaemon();
                         id = getUniqueId();
-                        if (discoverServices(id, servInfo.getServiceType())) {
+                        if (discoverServices(id, args.serviceInfo.getServiceType())) {
                             if (DBG) {
                                 Slog.d(TAG, "Discover " + msg.arg2 + " " + id +
-                                        servInfo.getServiceType());
+                                        args.serviceInfo.getServiceType());
                             }
-                            storeRequestMap(msg.arg2, id, clientInfo, msg.what);
-                            replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo);
+                            storeRequestMap(clientId, id, clientInfo, msg.what);
+                            clientInfo.onDiscoverServicesStarted(clientId, args.serviceInfo);
                         } else {
                             stopServiceDiscovery(id);
-                            replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
+                            clientInfo.onDiscoverServicesFailed(clientId,
                                     NsdManager.FAILURE_INTERNAL_ERROR);
                         }
                         break;
                     case NsdManager.STOP_DISCOVERY:
                         if (DBG) Slog.d(TAG, "Stop service discovery");
-                        clientInfo = mClients.get(msg.replyTo);
+                        args = (ListenerArgs) msg.obj;
+                        clientInfo = mClients.get(args.connector);
 
                         try {
-                            id = clientInfo.mClientIds.get(msg.arg2);
+                            id = clientInfo.mClientIds.get(clientId);
                         } catch (NullPointerException e) {
-                            replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
-                                    NsdManager.FAILURE_INTERNAL_ERROR);
+                            clientInfo.onStopDiscoveryFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                             break;
                         }
-                        removeRequestMap(msg.arg2, id, clientInfo);
+                        removeRequestMap(clientId, id, clientInfo);
                         if (stopServiceDiscovery(id)) {
-                            replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED);
+                            clientInfo.onStopDiscoverySucceeded(clientId);
                         } else {
-                            replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
-                                    NsdManager.FAILURE_INTERNAL_ERROR);
+                            clientInfo.onStopDiscoveryFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         }
                         break;
                     case NsdManager.REGISTER_SERVICE:
                         if (DBG) Slog.d(TAG, "Register service");
-                        clientInfo = mClients.get(msg.replyTo);
+                        args = (ListenerArgs) msg.obj;
+                        clientInfo = mClients.get(args.connector);
                         if (requestLimitReached(clientInfo)) {
-                            replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
-                                    NsdManager.FAILURE_MAX_LIMIT);
+                            clientInfo.onRegisterServiceFailed(
+                                    clientId, NsdManager.FAILURE_MAX_LIMIT);
                             break;
                         }
 
                         maybeStartDaemon();
                         id = getUniqueId();
-                        if (registerService(id, (NsdServiceInfo) msg.obj)) {
-                            if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id);
-                            storeRequestMap(msg.arg2, id, clientInfo, msg.what);
+                        if (registerService(id, args.serviceInfo)) {
+                            if (DBG) Slog.d(TAG, "Register " + clientId + " " + id);
+                            storeRequestMap(clientId, id, clientInfo, msg.what);
                             // Return success after mDns reports success
                         } else {
                             unregisterService(id);
-                            replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
-                                    NsdManager.FAILURE_INTERNAL_ERROR);
+                            clientInfo.onRegisterServiceFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         }
                         break;
                     case NsdManager.UNREGISTER_SERVICE:
                         if (DBG) Slog.d(TAG, "unregister service");
-                        clientInfo = mClients.get(msg.replyTo);
-                        try {
-                            id = clientInfo.mClientIds.get(msg.arg2);
-                        } catch (NullPointerException e) {
-                            replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
-                                    NsdManager.FAILURE_INTERNAL_ERROR);
+                        args = (ListenerArgs) msg.obj;
+                        clientInfo = mClients.get(args.connector);
+                        if (clientInfo == null) {
+                            Slog.e(TAG, "Unknown connector in unregistration");
                             break;
                         }
-                        removeRequestMap(msg.arg2, id, clientInfo);
+                        id = clientInfo.mClientIds.get(clientId);
+                        removeRequestMap(clientId, id, clientInfo);
                         if (unregisterService(id)) {
-                            replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED);
+                            clientInfo.onUnregisterServiceSucceeded(clientId);
                         } else {
-                            replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
-                                    NsdManager.FAILURE_INTERNAL_ERROR);
+                            clientInfo.onUnregisterServiceFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         }
                         break;
                     case NsdManager.RESOLVE_SERVICE:
                         if (DBG) Slog.d(TAG, "Resolve service");
-                        servInfo = (NsdServiceInfo) msg.obj;
-                        clientInfo = mClients.get(msg.replyTo);
-
+                        args = (ListenerArgs) msg.obj;
+                        clientInfo = mClients.get(args.connector);
 
                         if (clientInfo.mResolvedService != null) {
-                            replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
-                                    NsdManager.FAILURE_ALREADY_ACTIVE);
+                            clientInfo.onResolveServiceFailed(
+                                    clientId, NsdManager.FAILURE_ALREADY_ACTIVE);
                             break;
                         }
 
                         maybeStartDaemon();
                         id = getUniqueId();
-                        if (resolveService(id, servInfo)) {
+                        if (resolveService(id, args.serviceInfo)) {
                             clientInfo.mResolvedService = new NsdServiceInfo();
-                            storeRequestMap(msg.arg2, id, clientInfo, msg.what);
+                            storeRequestMap(clientId, id, clientInfo, msg.what);
                         } else {
-                            replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
-                                    NsdManager.FAILURE_INTERNAL_ERROR);
+                            clientInfo.onResolveServiceFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         }
                         break;
                     case NsdManager.NATIVE_DAEMON_EVENT:
@@ -449,30 +454,27 @@
                     case NativeResponseCode.SERVICE_FOUND:
                         /* NNN uniqueId serviceName regType domain */
                         servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
-                        clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0,
-                                clientId, servInfo);
+                        clientInfo.onServiceFound(clientId, servInfo);
                         break;
                     case NativeResponseCode.SERVICE_LOST:
                         /* NNN uniqueId serviceName regType domain */
                         servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
-                        clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0,
-                                clientId, servInfo);
+                        clientInfo.onServiceLost(clientId, servInfo);
                         break;
                     case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
                         /* NNN uniqueId errorCode */
-                        clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED,
-                                NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+                        clientInfo.onDiscoverServicesFailed(
+                                clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         break;
                     case NativeResponseCode.SERVICE_REGISTERED:
                         /* NNN regId serviceName regType */
                         servInfo = new NsdServiceInfo(cooked[2], null);
-                        clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED,
-                                id, clientId, servInfo);
+                        clientInfo.onRegisterServiceSucceeded(clientId, servInfo);
                         break;
                     case NativeResponseCode.SERVICE_REGISTRATION_FAILED:
                         /* NNN regId errorCode */
-                        clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED,
-                               NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+                        clientInfo.onRegisterServiceFailed(
+                                clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         break;
                     case NativeResponseCode.SERVICE_UPDATED:
                         /* NNN regId */
@@ -511,8 +513,8 @@
                         if (getAddrInfo(id2, cooked[3])) {
                             storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE);
                         } else {
-                            clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
-                                    NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+                            clientInfo.onResolveServiceFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                             clientInfo.mResolvedService = null;
                         }
                         break;
@@ -521,26 +523,26 @@
                         stopResolveService(id);
                         removeRequestMap(clientId, id, clientInfo);
                         clientInfo.mResolvedService = null;
-                        clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
-                                NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+                        clientInfo.onResolveServiceFailed(
+                                clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         break;
                     case NativeResponseCode.SERVICE_GET_ADDR_FAILED:
                         /* NNN resolveId errorCode */
                         stopGetAddrInfo(id);
                         removeRequestMap(clientId, id, clientInfo);
                         clientInfo.mResolvedService = null;
-                        clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
-                                NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+                        clientInfo.onResolveServiceFailed(
+                                clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         break;
                     case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS:
                         /* NNN resolveId hostname ttl addr */
                         try {
                             clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4]));
-                            clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED,
-                                   0, clientId, clientInfo.mResolvedService);
+                            clientInfo.onResolveServiceSucceeded(
+                                    clientId, clientInfo.mResolvedService);
                         } catch (java.net.UnknownHostException e) {
-                            clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
-                                    NsdManager.FAILURE_INTERNAL_ERROR, clientId);
+                            clientInfo.onResolveServiceFailed(
+                                    clientId, NsdManager.FAILURE_INTERNAL_ERROR);
                         }
                         stopGetAddrInfo(id);
                         removeRequestMap(clientId, id, clientInfo);
@@ -601,15 +603,71 @@
         return service;
     }
 
-    public Messenger getMessenger() {
+    @Override
+    public INsdServiceConnector connect(INsdManagerCallback cb) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET, "NsdService");
-        return new Messenger(mNsdStateMachine.getHandler());
+        final INsdServiceConnector connector = new NsdServiceConnector();
+        mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+                NsdManager.REGISTER_CLIENT, new Pair<>(connector, cb)));
+        return connector;
     }
 
-    public void setEnabled(boolean isEnabled) {
-        NetworkStack.checkNetworkStackPermission(mContext);
-        mNsdSettings.putEnabledStatus(isEnabled);
-        notifyEnabled(isEnabled);
+    private static class ListenerArgs {
+        public final NsdServiceConnector connector;
+        public final NsdServiceInfo serviceInfo;
+        ListenerArgs(NsdServiceConnector connector, NsdServiceInfo serviceInfo) {
+            this.connector = connector;
+            this.serviceInfo = serviceInfo;
+        }
+    }
+
+    private class NsdServiceConnector extends INsdServiceConnector.Stub
+            implements IBinder.DeathRecipient  {
+        @Override
+        public void registerService(int listenerKey, NsdServiceInfo serviceInfo) {
+            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+                    NsdManager.REGISTER_SERVICE, 0, listenerKey,
+                    new ListenerArgs(this, serviceInfo)));
+        }
+
+        @Override
+        public void unregisterService(int listenerKey) {
+            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+                    NsdManager.UNREGISTER_SERVICE, 0, listenerKey,
+                    new ListenerArgs(this, null)));
+        }
+
+        @Override
+        public void discoverServices(int listenerKey, NsdServiceInfo serviceInfo) {
+            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+                    NsdManager.DISCOVER_SERVICES, 0, listenerKey,
+                    new ListenerArgs(this, serviceInfo)));
+        }
+
+        @Override
+        public void stopDiscovery(int listenerKey) {
+            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+                    NsdManager.STOP_DISCOVERY, 0, listenerKey, new ListenerArgs(this, null)));
+        }
+
+        @Override
+        public void resolveService(int listenerKey, NsdServiceInfo serviceInfo) {
+            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+                    NsdManager.RESOLVE_SERVICE, 0, listenerKey,
+                    new ListenerArgs(this, serviceInfo)));
+        }
+
+        @Override
+        public void startDaemon() {
+            mNsdStateMachine.sendMessage(mNsdStateMachine.obtainMessage(
+                    NsdManager.DAEMON_STARTUP, new ListenerArgs(this, null)));
+        }
+
+        @Override
+        public void binderDied() {
+            mNsdStateMachine.sendMessage(
+                    mNsdStateMachine.obtainMessage(NsdManager.UNREGISTER_CLIENT, this));
+        }
     }
 
     private void notifyEnabled(boolean isEnabled) {
@@ -832,43 +890,11 @@
         mNsdStateMachine.dump(fd, pw, args);
     }
 
-    /* arg2 on the source message has an id that needs to be retained in replies
-     * see NsdManager for details */
-    private Message obtainMessage(Message srcMsg) {
-        Message msg = Message.obtain();
-        msg.arg2 = srcMsg.arg2;
-        return msg;
-    }
-
-    private void replyToMessage(Message msg, int what) {
-        if (msg.replyTo == null) return;
-        Message dstMsg = obtainMessage(msg);
-        dstMsg.what = what;
-        mReplyChannel.replyToMessage(msg, dstMsg);
-    }
-
-    private void replyToMessage(Message msg, int what, int arg1) {
-        if (msg.replyTo == null) return;
-        Message dstMsg = obtainMessage(msg);
-        dstMsg.what = what;
-        dstMsg.arg1 = arg1;
-        mReplyChannel.replyToMessage(msg, dstMsg);
-    }
-
-    private void replyToMessage(Message msg, int what, Object obj) {
-        if (msg.replyTo == null) return;
-        Message dstMsg = obtainMessage(msg);
-        dstMsg.what = what;
-        dstMsg.obj = obj;
-        mReplyChannel.replyToMessage(msg, dstMsg);
-    }
-
     /* Information tracked per client */
     private class ClientInfo {
 
         private static final int MAX_LIMIT = 10;
-        private final AsyncChannel mChannel;
-        private final Messenger mMessenger;
+        private final INsdManagerCallback mCb;
         /* Remembers a resolved service until getaddrinfo completes */
         private NsdServiceInfo mResolvedService;
 
@@ -881,17 +907,14 @@
         // The target SDK of this client < Build.VERSION_CODES.S
         private boolean mIsLegacy = false;
 
-        private ClientInfo(AsyncChannel c, Messenger m) {
-            mChannel = c;
-            mMessenger = m;
-            if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m);
+        private ClientInfo(INsdManagerCallback cb) {
+            mCb = cb;
+            if (DBG) Slog.d(TAG, "New client");
         }
 
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder();
-            sb.append("mChannel ").append(mChannel).append("\n");
-            sb.append("mMessenger ").append(mMessenger).append("\n");
             sb.append("mResolvedService ").append(mResolvedService).append("\n");
             sb.append("mIsLegacy ").append(mIsLegacy).append("\n");
             for(int i = 0; i< mClientIds.size(); i++) {
@@ -949,6 +972,102 @@
             }
             return mClientIds.keyAt(idx);
         }
+
+        void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) {
+            try {
+                mCb.onDiscoverServicesStarted(listenerKey, info);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onDiscoverServicesStarted", e);
+            }
+        }
+
+        void onDiscoverServicesFailed(int listenerKey, int error) {
+            try {
+                mCb.onDiscoverServicesFailed(listenerKey, error);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onDiscoverServicesFailed", e);
+            }
+        }
+
+        void onServiceFound(int listenerKey, NsdServiceInfo info) {
+            try {
+                mCb.onServiceFound(listenerKey, info);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onServiceFound(", e);
+            }
+        }
+
+        void onServiceLost(int listenerKey, NsdServiceInfo info) {
+            try {
+                mCb.onServiceLost(listenerKey, info);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onServiceLost(", e);
+            }
+        }
+
+        void onStopDiscoveryFailed(int listenerKey, int error) {
+            try {
+                mCb.onStopDiscoveryFailed(listenerKey, error);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onStopDiscoveryFailed", e);
+            }
+        }
+
+        void onStopDiscoverySucceeded(int listenerKey) {
+            try {
+                mCb.onStopDiscoverySucceeded(listenerKey);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onStopDiscoverySucceeded", e);
+            }
+        }
+
+        void onRegisterServiceFailed(int listenerKey, int error) {
+            try {
+                mCb.onRegisterServiceFailed(listenerKey, error);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onRegisterServiceFailed", e);
+            }
+        }
+
+        void onRegisterServiceSucceeded(int listenerKey, NsdServiceInfo info) {
+            try {
+                mCb.onRegisterServiceSucceeded(listenerKey, info);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onRegisterServiceSucceeded", e);
+            }
+        }
+
+        void onUnregisterServiceFailed(int listenerKey, int error) {
+            try {
+                mCb.onUnregisterServiceFailed(listenerKey, error);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onUnregisterServiceFailed", e);
+            }
+        }
+
+        void onUnregisterServiceSucceeded(int listenerKey) {
+            try {
+                mCb.onUnregisterServiceSucceeded(listenerKey);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onUnregisterServiceSucceeded", e);
+            }
+        }
+
+        void onResolveServiceFailed(int listenerKey, int error) {
+            try {
+                mCb.onResolveServiceFailed(listenerKey, error);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onResolveServiceFailed", e);
+            }
+        }
+
+        void onResolveServiceSucceeded(int listenerKey, NsdServiceInfo info) {
+            try {
+                mCb.onResolveServiceSucceeded(listenerKey, info);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Error calling onResolveServiceSucceeded", e);
+            }
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 311555e..1929df8 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -1223,7 +1223,7 @@
             }
             for (int i = 0; i < mVolumes.size(); i++) {
                 final VolumeInfo vol = mVolumes.valueAt(i);
-                if (vol.isVisibleForRead(userId) && vol.isMountedReadable()) {
+                if (vol.isVisibleForUser(userId) && vol.isMountedReadable()) {
                     final StorageVolume userVol = vol.buildStorageVolume(mContext, userId, false);
                     mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
 
@@ -1570,7 +1570,7 @@
                     || Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
                 Slog.v(TAG, "Found primary storage at " + vol);
                 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
-                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
+                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE;
                 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
             }
 
@@ -1580,13 +1580,13 @@
                     && vol.disk.isDefaultPrimary()) {
                 Slog.v(TAG, "Found primary storage at " + vol);
                 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
-                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
+                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE;
             }
 
             // Adoptable public disks are visible to apps, since they meet
             // public API requirement of being in a stable location.
             if (vol.disk.isAdoptable()) {
-                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
+                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE;
             }
 
             vol.mountUserId = mCurrentUserId;
@@ -1597,7 +1597,7 @@
 
         } else if (vol.type == VolumeInfo.TYPE_STUB) {
             if (vol.disk.isStubVisible()) {
-                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
+                vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE_FOR_WRITE;
             }
             vol.mountUserId = mCurrentUserId;
             mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
@@ -1744,7 +1744,7 @@
                 // started after this point will trigger additional
                 // user-specific broadcasts.
                 for (int userId : mSystemUnlockedUsers) {
-                    if (vol.isVisibleForRead(userId)) {
+                    if (vol.isVisibleForUser(userId)) {
                         final StorageVolume userVol = vol.buildStorageVolume(mContext, userId,
                                 false);
                         mHandler.obtainMessage(H_VOLUME_BROADCAST, userVol).sendToTarget();
@@ -3565,24 +3565,24 @@
         }
 
         @Override
-        public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
+        public ParcelFileDescriptor open() throws AppFuseMountException {
             try {
                 final FileDescriptor fd = mVold.mountAppFuse(uid, mountId);
                 mMounted = true;
                 return new ParcelFileDescriptor(fd);
             } catch (Exception e) {
-                throw new NativeDaemonConnectorException("Failed to mount", e);
+                throw new AppFuseMountException("Failed to mount", e);
             }
         }
 
         @Override
         public ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
-                throws NativeDaemonConnectorException {
+                throws AppFuseMountException {
             try {
                 return new ParcelFileDescriptor(
                         mVold.openAppFuseFile(uid, mountId, fileId, flags));
             } catch (Exception e) {
-                throw new NativeDaemonConnectorException("Failed to open", e);
+                throw new AppFuseMountException("Failed to open", e);
             }
         }
 
@@ -3622,7 +3622,7 @@
                         // It seems the thread of mAppFuseBridge has already been terminated.
                         mAppFuseBridge = null;
                     }
-                } catch (NativeDaemonConnectorException e) {
+                } catch (AppFuseMountException e) {
                     throw e.rethrowAsParcelableException();
                 }
             }
@@ -3713,8 +3713,19 @@
     }
 
     @Override
-    public StorageVolume[] getVolumeList(int uid, String packageName, int flags) {
-        final int userId = UserHandle.getUserId(uid);
+    public StorageVolume[] getVolumeList(int userId, String callingPackage, int flags) {
+        final int callingUid = Binder.getCallingUid();
+        final int callingUserId = UserHandle.getUserId(callingUid);
+
+        if (!isUidOwnerOfPackageOrSystem(callingPackage, callingUid)) {
+            throw new SecurityException("callingPackage does not match UID");
+        }
+        if (callingUserId != userId) {
+            // Callers can ask for volumes of different users, but only with the correct permissions
+            mContext.enforceCallingOrSelfPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS,
+                    "Need INTERACT_ACROSS_USERS to get volumes for another user");
+        }
 
         final boolean forWrite = (flags & StorageManager.FLAG_FOR_WRITE) != 0;
         final boolean realState = (flags & StorageManager.FLAG_REAL_STATE) != 0;
@@ -3730,7 +3741,7 @@
         // should never attempt to augment the actual storage volume state,
         // otherwise we risk confusing it with race conditions as users go
         // through various unlocked states
-        final boolean callerIsMediaStore = UserHandle.isSameApp(Binder.getCallingUid(),
+        final boolean callerIsMediaStore = UserHandle.isSameApp(callingUid,
                 mMediaStoreAuthorityAppId);
 
         final boolean userIsDemo;
@@ -3740,8 +3751,9 @@
         try {
             userIsDemo = LocalServices.getService(UserManagerInternal.class)
                     .getUserInfo(userId).isDemo();
+            storagePermission = mStorageManagerInternal.hasExternalStorage(callingUid,
+                    callingPackage);
             userKeyUnlocked = isUserKeyUnlocked(userId);
-            storagePermission = mStorageManagerInternal.hasExternalStorage(uid, packageName);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
@@ -3771,7 +3783,7 @@
                 if (forWrite) {
                     match = vol.isVisibleForWrite(userId);
                 } else {
-                    match = vol.isVisibleForRead(userId)
+                    match = vol.isVisibleForUser(userId)
                             || (includeInvisible && vol.getPath() != null);
                 }
                 if (!match) continue;
diff --git a/services/core/java/com/android/server/VcnManagementService.java b/services/core/java/com/android/server/VcnManagementService.java
index b068f86..0c990ec 100644
--- a/services/core/java/com/android/server/VcnManagementService.java
+++ b/services/core/java/com/android/server/VcnManagementService.java
@@ -141,7 +141,7 @@
  *                      |                     or its properties
  *                      v                              |
  * +-----------------------------------------------------------------------+
- * |                       UnderlyingNetworkTracker                        |
+ * |                       UnderlyingNetworkController                     |
  * |                                                                       |
  * | Manages lifecycle of underlying physical networks, filing requests to |
  * | bring them up, and releasing them as they become no longer necessary  |
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index b019789..ac20a08 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -685,6 +685,7 @@
             final UUID errorId = mTraceErrorLogger.generateErrorId();
             if (mTraceErrorLogger.isAddErrorIdEnabled()) {
                 mTraceErrorLogger.addErrorIdToTrace("system_server", errorId);
+                mTraceErrorLogger.addSubjectToTrace(subject, errorId);
             }
 
             // Log the atom as early as possible since it is used as a mechanism to trigger
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index bf744cf..6decdb9 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -87,7 +87,6 @@
 import android.app.ActivityThread;
 import android.app.AppGlobals;
 import android.app.AppOpsManager;
-import android.app.ForegroundServiceDidNotStartInTimeException;
 import android.app.ForegroundServiceStartNotAllowedException;
 import android.app.IApplicationThread;
 import android.app.IForegroundServiceObserver;
@@ -95,6 +94,7 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.RemoteServiceException.ForegroundServiceDidNotStartInTimeException;
 import android.app.Service;
 import android.app.ServiceStartArgs;
 import android.app.admin.DevicePolicyEventLogger;
@@ -861,7 +861,7 @@
                 final ServiceState stracker = r.getTracker();
                 if (stracker != null) {
                     stracker.setForeground(true, mAm.mProcessStats.getMemFactorLocked(),
-                            r.lastActivity);
+                            SystemClock.uptimeMillis()); // Use current time, not lastActivity.
                 }
             }
             mAm.mAppOpsService.startOperation(AppOpsManager.getToken(mAm.mAppOpsService),
@@ -1137,7 +1137,8 @@
         synchronized (mAm.mProcessStats.mLock) {
             final ServiceState stracker = r.getTracker();
             if (stracker != null) {
-                stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
+                stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(),
+                        SystemClock.uptimeMillis()); // Use current time, not lastActivity.
             }
         }
         r.callStart = false;
@@ -1293,7 +1294,7 @@
     }
 
     void killMisbehavingService(ServiceRecord r,
-            int appUid, int appPid, String localPackageName) {
+            int appUid, int appPid, String localPackageName, int exceptionTypeId) {
         synchronized (mAm) {
             if (!r.destroying) {
                 // This service is still alive, stop it.
@@ -1307,8 +1308,8 @@
                     stopServiceLocked(found, false);
                 }
             }
-            mAm.crashApplication(appUid, appPid, localPackageName, -1,
-                    "Bad notification for startForeground", true /*force*/);
+            mAm.crashApplicationWithType(appUid, appPid, localPackageName, -1,
+                    "Bad notification for startForeground", true /*force*/, exceptionTypeId);
         }
     }
 
@@ -1974,7 +1975,8 @@
                                 final ServiceState stracker = r.getTracker();
                                 if (stracker != null) {
                                     stracker.setForeground(true,
-                                            mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
+                                            mAm.mProcessStats.getMemFactorLocked(),
+                                            SystemClock.uptimeMillis());
                                 }
                             }
                         } else {
@@ -2843,7 +2845,7 @@
                         final ServiceState stracker = s.getTracker();
                         if (stracker != null) {
                             stracker.setBound(true, mAm.mProcessStats.getMemFactorLocked(),
-                                    s.lastActivity);
+                                    SystemClock.uptimeMillis());
                         }
                     }
                 }
@@ -3509,14 +3511,14 @@
             timeoutNeeded = false;
         }
 
-        long now = SystemClock.uptimeMillis();
         ProcessServiceRecord psr;
         if (r.executeNesting == 0) {
             r.executeFg = fg;
             synchronized (mAm.mProcessStats.mLock) {
                 final ServiceState stracker = r.getTracker();
                 if (stracker != null) {
-                    stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(), now);
+                    stracker.setExecuting(true, mAm.mProcessStats.getMemFactorLocked(),
+                            SystemClock.uptimeMillis());
                 }
             }
             if (r.app != null) {
@@ -3547,7 +3549,7 @@
         }
         r.executeFg |= fg;
         r.executeNesting++;
-        r.executingStart = now;
+        r.executingStart = SystemClock.uptimeMillis();
         return oomAdjusted;
     }
 
@@ -3734,7 +3736,8 @@
             if (oldPosInRestarting == -1) {
                 r.createdFromFg = false;
                 synchronized (mAm.mProcessStats.mLock) {
-                    r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now);
+                    r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(),
+                            SystemClock.uptimeMillis());
                 }
             }
             boolean added = false;
@@ -4500,7 +4503,6 @@
             }
         }
 
-        final long now = SystemClock.uptimeMillis();
         // Check to see if the service had been started as foreground, but being
         // brought down before actually showing a notification.  That is not allowed.
         if (r.fgRequired) {
@@ -4511,7 +4513,8 @@
             synchronized (mAm.mProcessStats.mLock) {
                 ServiceState stracker = r.getTracker();
                 if (stracker != null) {
-                    stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), now);
+                    stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
+                            SystemClock.uptimeMillis());
                 }
             }
             mAm.mAppOpsService.finishOperation(AppOpsManager.getToken(mAm.mAppOpsService),
@@ -4573,7 +4576,8 @@
             synchronized (mAm.mProcessStats.mLock) {
                 ServiceState stracker = r.getTracker();
                 if (stracker != null) {
-                    stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(), now);
+                    stracker.setForeground(false, mAm.mProcessStats.getMemFactorLocked(),
+                            SystemClock.uptimeMillis());
                 }
             }
             mAm.mAppOpsService.finishOperation(
@@ -4650,6 +4654,7 @@
         synchronized (mAm.mProcessStats.mLock) {
             final int memFactor = mAm.mProcessStats.getMemFactorLocked();
             if (r.tracker != null) {
+                final long now = SystemClock.uptimeMillis();
                 r.tracker.setStarted(false, memFactor, now);
                 r.tracker.setBound(false, memFactor, now);
                 if (r.executeNesting == 0) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 4c2cd53..02a16fc 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -186,7 +186,6 @@
 import android.app.ProcessMemoryState;
 import android.app.ProfilerInfo;
 import android.app.PropertyInvalidatedCache;
-import android.app.RemoteServiceException;
 import android.app.SyncNotedAppOp;
 import android.app.WaitResult;
 import android.app.backup.BackupManager.OperationType;
@@ -643,10 +642,11 @@
 
     final BroadcastQueue mFgBroadcastQueue;
     final BroadcastQueue mBgBroadcastQueue;
-    final BroadcastQueue mOffloadBroadcastQueue;
+    final BroadcastQueue mBgOffloadBroadcastQueue;
+    final BroadcastQueue mFgOffloadBroadcastQueue;
     // Convenient for easy iteration over the queues. Foreground is first
     // so that dispatch of foreground broadcasts gets precedence.
-    final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[3];
+    final BroadcastQueue[] mBroadcastQueues = new BroadcastQueue[4];
 
     @GuardedBy("this")
     BroadcastStats mLastBroadcastStats;
@@ -657,12 +657,20 @@
     TraceErrorLogger mTraceErrorLogger;
 
     BroadcastQueue broadcastQueueForIntent(Intent intent) {
-        if (isOnOffloadQueue(intent.getFlags())) {
+        if (isOnFgOffloadQueue(intent.getFlags())) {
             if (DEBUG_BROADCAST_BACKGROUND) {
                 Slog.i(TAG_BROADCAST,
-                        "Broadcast intent " + intent + " on offload queue");
+                        "Broadcast intent " + intent + " on foreground offload queue");
             }
-            return mOffloadBroadcastQueue;
+            return mFgOffloadBroadcastQueue;
+        }
+
+        if (isOnBgOffloadQueue(intent.getFlags())) {
+            if (DEBUG_BROADCAST_BACKGROUND) {
+                Slog.i(TAG_BROADCAST,
+                        "Broadcast intent " + intent + " on background offload queue");
+            }
+            return mBgOffloadBroadcastQueue;
         }
 
         final boolean isFg = (intent.getFlags() & Intent.FLAG_RECEIVER_FOREGROUND) != 0;
@@ -2264,7 +2272,8 @@
         mPendingStartActivityUids = new PendingStartActivityUids(mContext);
         mUseFifoUiScheduling = false;
         mEnableOffloadQueue = false;
-        mFgBroadcastQueue = mBgBroadcastQueue = mOffloadBroadcastQueue = null;
+        mFgBroadcastQueue = mBgBroadcastQueue = mBgOffloadBroadcastQueue =
+                mFgOffloadBroadcastQueue = null;
         mComponentAliasResolver = new ComponentAliasResolver(this);
     }
 
@@ -2325,11 +2334,14 @@
                 "foreground", foreConstants, false);
         mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
                 "background", backConstants, true);
-        mOffloadBroadcastQueue = new BroadcastQueue(this, mHandler,
-                "offload", offloadConstants, true);
+        mBgOffloadBroadcastQueue = new BroadcastQueue(this, mHandler,
+                "offload_bg", offloadConstants, true);
+        mFgOffloadBroadcastQueue = new BroadcastQueue(this, mHandler,
+                "offload_fg", foreConstants, true);
         mBroadcastQueues[0] = mFgBroadcastQueue;
         mBroadcastQueues[1] = mBgBroadcastQueue;
-        mBroadcastQueues[2] = mOffloadBroadcastQueue;
+        mBroadcastQueues[2] = mBgOffloadBroadcastQueue;
+        mBroadcastQueues[3] = mFgOffloadBroadcastQueue;
 
         mServices = new ActiveServices(this);
         mCpHelper = new ContentProviderHelper(this, true);
@@ -3034,13 +3046,6 @@
     }
 
     @Override
-    public void crashApplication(int uid, int initialPid, String packageName, int userId,
-            String message, boolean force) {
-        crashApplicationWithType(uid, initialPid, packageName, userId, message, force,
-                RemoteServiceException.TYPE_ID);
-    }
-
-    @Override
     public void crashApplicationWithType(int uid, int initialPid, String packageName, int userId,
             String message, boolean force, int exceptionTypeId) {
         if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
@@ -4666,7 +4671,8 @@
                         app.getCompat(), getCommonServicesLocked(app.isolated),
                         mCoreSettingsObserver.getCoreSettingsLocked(),
                         buildSerial, autofillOptions, contentCaptureOptions,
-                        app.getDisabledCompatChanges(), serializedSystemFontMap);
+                        app.getDisabledCompatChanges(), serializedSystemFontMap,
+                        app.getStartElapsedTime(), app.getStartUptime());
             } else {
                 thread.bindApplication(processName, appInfo, providerList, null, profilerInfo,
                         null, null, null, testMode,
@@ -4676,7 +4682,8 @@
                         app.getCompat(), getCommonServicesLocked(app.isolated),
                         mCoreSettingsObserver.getCoreSettingsLocked(),
                         buildSerial, autofillOptions, contentCaptureOptions,
-                        app.getDisabledCompatChanges(), serializedSystemFontMap);
+                        app.getDisabledCompatChanges(), serializedSystemFontMap,
+                        app.getStartElapsedTime(), app.getStartUptime());
             }
             if (profilerInfo != null) {
                 profilerInfo.closeFd();
@@ -11951,6 +11958,15 @@
         // If this is a preceding instance of another process instance
         allowRestart = mProcessList.handlePrecedingAppDiedLocked(app);
 
+        // If somehow this process was still waiting for the death of its predecessor,
+        // (probably it's "killed" before starting for real), reset the bookkeeping.
+        final ProcessRecord predecessor = app.mPredecessor;
+        if (predecessor != null) {
+            predecessor.mSuccessor = null;
+            predecessor.mSuccessorStartRunnable = null;
+            app.mPredecessor = null;
+        }
+
         // If the caller is restarting this app, then leave it in its
         // current lists and let the caller take care of it.
         if (restarting) {
@@ -12549,13 +12565,15 @@
     boolean isPendingBroadcastProcessLocked(int pid) {
         return mFgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
                 || mBgBroadcastQueue.isPendingBroadcastProcessLocked(pid)
-                || mOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid);
+                || mBgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid)
+                || mFgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(pid);
     }
 
     boolean isPendingBroadcastProcessLocked(ProcessRecord app) {
         return mFgBroadcastQueue.isPendingBroadcastProcessLocked(app)
                 || mBgBroadcastQueue.isPendingBroadcastProcessLocked(app)
-                || mOffloadBroadcastQueue.isPendingBroadcastProcessLocked(app);
+                || mBgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(app)
+                || mFgOffloadBroadcastQueue.isPendingBroadcastProcessLocked(app);
     }
 
     void skipPendingBroadcastLocked(int pid) {
@@ -12672,30 +12690,38 @@
                         "Receiver can't specify both RECEIVER_EXPORTED and RECEIVER_NOT_EXPORTED"
                                 + "flag");
             }
-            if (CompatChanges.isChangeEnabled(DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED,
-                    callingUid)
-                    && !explicitExportStateDefined) {
-                if (ENFORCE_DYNAMIC_RECEIVER_EXPLICIT_EXPORT) {
-                    throw new SecurityException(
-                            callerPackage + ": Targeting T+ (version "
-                                    + Build.VERSION_CODES.TIRAMISU
-                                    + " and above) requires that one of RECEIVER_EXPORTED or "
-                                    + "RECEIVER_NOT_EXPORTED be specified when registering a "
-                                    + "receiver");
-                } else {
-                    Slog.wtf(TAG,
-                            callerPackage + ": Targeting T+ (version "
-                                    + Build.VERSION_CODES.TIRAMISU
-                                    + " and above) requires that one of RECEIVER_EXPORTED or "
-                                    + "RECEIVER_NOT_EXPORTED be specified when registering a "
-                                    + "receiver");
-                    // Assume default behavior-- flag check is not enforced
+
+            // Don't enforce the flag check if we're EITHER registering for only protected
+            // broadcasts, or the receiver is null (a sticky broadcast). Sticky broadcasts should
+            // not be used generally, so we will be marking them as exported by default
+            final boolean requireExplicitFlagForDynamicReceivers = CompatChanges.isChangeEnabled(
+                    DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED, callingUid);
+            if (!onlyProtectedBroadcasts) {
+                if (receiver == null && !explicitExportStateDefined) {
+                    // sticky broadcast, no flag specified (flag isn't required)
+                    flags |= Context.RECEIVER_EXPORTED;
+                } else if (requireExplicitFlagForDynamicReceivers && !explicitExportStateDefined) {
+                    if (ENFORCE_DYNAMIC_RECEIVER_EXPLICIT_EXPORT) {
+                        throw new SecurityException(
+                                callerPackage + ": Targeting T+ (version "
+                                        + Build.VERSION_CODES.TIRAMISU
+                                        + " and above) requires that one of RECEIVER_EXPORTED or "
+                                        + "RECEIVER_NOT_EXPORTED be specified when registering a "
+                                        + "receiver");
+                    } else {
+                        Slog.wtf(TAG,
+                                callerPackage + ": Targeting T+ (version "
+                                        + Build.VERSION_CODES.TIRAMISU
+                                        + " and above) requires that one of RECEIVER_EXPORTED or "
+                                        + "RECEIVER_NOT_EXPORTED be specified when registering a "
+                                        + "receiver");
+                        // Assume default behavior-- flag check is not enforced
+                        flags |= Context.RECEIVER_EXPORTED;
+                    }
+                } else if (!requireExplicitFlagForDynamicReceivers) {
+                    // Change is not enabled, thus not targeting T+. Assume exported.
                     flags |= Context.RECEIVER_EXPORTED;
                 }
-            } else if (!CompatChanges.isChangeEnabled(DYNAMIC_RECEIVER_EXPLICIT_EXPORT_REQUIRED,
-                    callingUid)) {
-                // Change is not enabled, thus not targeting T+. Assume exported.
-                flags |= Context.RECEIVER_EXPORTED;
             }
         }
 
@@ -12713,7 +12739,7 @@
                         (intent.getFlags() & Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS) == 0) {
                     continue;
                 }
-                // If intent has scheme "content", it will need to acccess
+                // If intent has scheme "content", it will need to access
                 // provider that needs to lock mProviderMap in ActivityThread
                 // and also it may need to wait application response, so we
                 // cannot lock ActivityManagerService here.
@@ -14004,8 +14030,10 @@
             BroadcastQueue queue;
 
             synchronized(this) {
-                if (isOnOffloadQueue(flags)) {
-                    queue = mOffloadBroadcastQueue;
+                if (isOnFgOffloadQueue(flags)) {
+                    queue = mFgOffloadBroadcastQueue;
+                } else if (isOnBgOffloadQueue(flags)) {
+                    queue = mBgOffloadBroadcastQueue;
                 } else {
                     queue = (flags & Intent.FLAG_RECEIVER_FOREGROUND) != 0
                             ? mFgBroadcastQueue : mBgBroadcastQueue;
@@ -14740,10 +14768,10 @@
     }
 
     @GuardedBy(anyOf = {"this", "mProcLock"})
-    final void setProcessTrackerStateLOSP(ProcessRecord proc, int memFactor, long now) {
+    final void setProcessTrackerStateLOSP(ProcessRecord proc, int memFactor) {
         if (proc.getThread() != null) {
             proc.mProfile.setProcessTrackerState(
-                    proc.mState.getReportedProcState(), memFactor, now);
+                    proc.mState.getReportedProcState(), memFactor);
         }
     }
 
@@ -15389,6 +15417,16 @@
     }
 
     @Override
+    public String getSwitchingFromUserMessage() {
+        return mUserController.getSwitchingFromSystemUserMessage();
+    }
+
+    @Override
+    public String getSwitchingToUserMessage() {
+        return mUserController.getSwitchingToSystemUserMessage();
+    }
+
+    @Override
     public void setStopUserOnSwitch(@StopUserOnSwitch int value) {
         mUserController.setStopUserOnSwitch(value);
     }
@@ -16299,7 +16337,7 @@
                         Binder.getCallingUid(), Binder.getCallingPid(), UserHandle.USER_ALL);
                 if ((changes & ActivityInfo.CONFIG_LOCALE) != 0) {
                     intent = new Intent(Intent.ACTION_LOCALE_CHANGED);
-                    intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
+                    intent.addFlags(Intent.FLAG_RECEIVER_OFFLOAD_FOREGROUND
                             | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
                             | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
                     if (initLocale || !mProcessesReady) {
@@ -17476,7 +17514,11 @@
         }
     }
 
-    private boolean isOnOffloadQueue(int flags) {
+    private boolean isOnFgOffloadQueue(int flags) {
+        return ((flags & Intent.FLAG_RECEIVER_OFFLOAD_FOREGROUND) != 0);
+    }
+
+    private boolean isOnBgOffloadQueue(int flags) {
         return (mEnableOffloadQueue && ((flags & Intent.FLAG_RECEIVER_OFFLOAD) != 0));
     }
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 5b33a71..c062365 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -46,6 +46,7 @@
 import android.app.IUidObserver;
 import android.app.KeyguardManager;
 import android.app.ProfilerInfo;
+import android.app.RemoteServiceException.CrashedByAdbException;
 import android.app.UserSwitchObserver;
 import android.app.WaitResult;
 import android.app.usage.AppStandbyInfo;
@@ -1173,7 +1174,8 @@
         } catch (NumberFormatException e) {
             packageName = arg;
         }
-        mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash", false);
+        mInterface.crashApplicationWithType(-1, pid, packageName, userId, "shell-induced crash",
+                false, CrashedByAdbException.TYPE_ID);
         return 0;
     }
 
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index d44d729..221de8d 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -953,7 +953,6 @@
 
     @GuardedBy({"mService", "mProcLock"})
     boolean updateLowMemStateLSP(int numCached, int numEmpty, int numTrimming) {
-        final long now = SystemClock.uptimeMillis();
         int memFactor;
         if (mLowMemDetector != null && mLowMemDetector.isAvailable()) {
             memFactor = mLowMemDetector.getMemFactor();
@@ -1008,7 +1007,9 @@
         mLastNumProcesses = mService.mProcessList.getLruSizeLOSP();
         boolean allChanged;
         int trackerMemFactor;
+        final long now;
         synchronized (mService.mProcessStats.mLock) {
+            now = SystemClock.uptimeMillis();
             allChanged = mService.mProcessStats.setMemFactorLocked(memFactor,
                     mService.mAtmInternal == null || !mService.mAtmInternal.isSleeping(), now);
             trackerMemFactor = mService.mProcessStats.getMemFactorLocked();
@@ -1044,7 +1045,7 @@
                 final int curProcState = state.getCurProcState();
                 IApplicationThread thread;
                 if (allChanged || state.hasProcStateChanged()) {
-                    mService.setProcessTrackerStateLOSP(app, trackerMemFactor, now);
+                    mService.setProcessTrackerStateLOSP(app, trackerMemFactor);
                     state.setProcStateChanged(false);
                 }
                 trimMemoryUiHiddenIfNecessaryLSP(app);
@@ -1113,7 +1114,7 @@
                 final IApplicationThread thread;
                 final ProcessStateRecord state = app.mState;
                 if (allChanged || state.hasProcStateChanged()) {
-                    mService.setProcessTrackerStateLOSP(app, trackerMemFactor, now);
+                    mService.setProcessTrackerStateLOSP(app, trackerMemFactor);
                     state.setProcStateChanged(false);
                 }
                 trimMemoryUiHiddenIfNecessaryLSP(app);
diff --git a/services/core/java/com/android/server/am/BaseErrorDialog.java b/services/core/java/com/android/server/am/BaseErrorDialog.java
index 7b5f2cd..259dd8ec 100644
--- a/services/core/java/com/android/server/am/BaseErrorDialog.java
+++ b/services/core/java/com/android/server/am/BaseErrorDialog.java
@@ -53,7 +53,7 @@
         mHandler.sendEmptyMessage(DISABLE_BUTTONS);
         mHandler.sendMessageDelayed(mHandler.obtainMessage(ENABLE_BUTTONS), 1000);
         getContext().registerReceiver(mReceiver,
-                new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
+                new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), Context.RECEIVER_EXPORTED);
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index fd6f099..592abbb 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -20,7 +20,13 @@
 import static android.os.Process.ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE;
 import static android.text.TextUtils.formatSimple;
 
-import static com.android.server.am.ActivityManagerDebugConfig.*;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_DEFERRAL;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_BROADCAST_LIGHT;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_MU;
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_PERMISSIONS_REVIEW;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_BROADCAST;
+import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_MU;
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
@@ -29,6 +35,7 @@
 import android.app.BroadcastOptions;
 import android.app.IApplicationThread;
 import android.app.PendingIntent;
+import android.app.RemoteServiceException.CannotDeliverBroadcastException;
 import android.app.usage.UsageEvents.Event;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -607,7 +614,8 @@
                     synchronized (mService) {
                         Slog.w(TAG, "Can't deliver broadcast to " + app.processName
                                 + " (pid " + app.getPid() + "). Crashing it.");
-                        app.scheduleCrashLocked("can't deliver broadcast");
+                        app.scheduleCrashLocked("can't deliver broadcast",
+                                CannotDeliverBroadcastException.TYPE_ID);
                     }
                     throw ex;
                 }
@@ -781,7 +789,7 @@
 
         // Ensure that broadcasts are only sent to other apps if they are explicitly marked as
         // exported, or are System level broadcasts
-        if (!skip && !filter.exported && Process.SYSTEM_UID != r.callingUid
+        if (!skip && !filter.exported && !Process.isCoreUid(r.callingUid)
                 && filter.receiverList.uid != r.callingUid) {
 
             Slog.w(TAG, "Exported Denial: sending "
@@ -792,7 +800,7 @@
                     + " due to receiver " + filter.receiverList.app
                     + " (uid " + filter.receiverList.uid + ")"
                     + " not specifying RECEIVER_EXPORTED");
-            skip = true;
+            // skip = true;
         }
 
         if (skip) {
diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java
index b434328..b6757c8 100644
--- a/services/core/java/com/android/server/am/ConnectionRecord.java
+++ b/services/core/java/com/android/server/am/ConnectionRecord.java
@@ -23,6 +23,7 @@
 import android.app.PendingIntent;
 import android.content.ComponentName;
 import android.content.Context;
+import android.os.SystemClock;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.util.proto.ProtoUtils;
@@ -158,10 +159,10 @@
         }
     }
 
-    public void trackProcState(int procState, int seq, long now) {
+    public void trackProcState(int procState, int seq) {
         if (association != null) {
             synchronized (mProcStatsLock) {
-                association.trackProcState(procState, seq, now);
+                association.trackProcState(procState, seq, SystemClock.uptimeMillis());
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/ContentProviderConnection.java b/services/core/java/com/android/server/am/ContentProviderConnection.java
index 3b9d47d..825b938 100644
--- a/services/core/java/com/android/server/am/ContentProviderConnection.java
+++ b/services/core/java/com/android/server/am/ContentProviderConnection.java
@@ -98,10 +98,13 @@
         }
     }
 
-    public void trackProcState(int procState, int seq, long now) {
+    /**
+     * Track the given proc state change.
+     */
+    public void trackProcState(int procState, int seq) {
         if (association != null) {
             synchronized (mProcStatsLock) {
-                association.trackProcState(procState, seq, now);
+                association.trackProcState(procState, seq, SystemClock.uptimeMillis());
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index dc9ecfe..47e24b1 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -874,13 +874,14 @@
         updateUidsLSP(activeUids, nowElapsed);
 
         synchronized (mService.mProcessStats.mLock) {
-            if (mService.mProcessStats.shouldWriteNowLocked(now)) {
+            final long nowUptime = SystemClock.uptimeMillis();
+            if (mService.mProcessStats.shouldWriteNowLocked(nowUptime)) {
                 mService.mHandler.post(new ActivityManagerService.ProcStatsRunnable(mService,
                         mService.mProcessStats));
             }
 
             // Run this after making sure all procstates are updated.
-            mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, now);
+            mService.mProcessStats.updateTrackingAssociationsLocked(mAdjSeq, nowUptime);
         }
 
         if (DEBUG_OOM_ADJ) {
@@ -1978,7 +1979,7 @@
                                         newAdj = ProcessList.PERSISTENT_SERVICE_ADJ;
                                         schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
                                         procState = ActivityManager.PROCESS_STATE_PERSISTENT;
-                                        cr.trackProcState(procState, mAdjSeq, now);
+                                        cr.trackProcState(procState, mAdjSeq);
                                         trackedProcState = true;
                                     }
                                 } else if ((cr.flags & Context.BIND_NOT_PERCEPTIBLE) != 0
@@ -2085,7 +2086,7 @@
                         }
 
                         if (!trackedProcState) {
-                            cr.trackProcState(clientProcState, mAdjSeq, now);
+                            cr.trackProcState(clientProcState, mAdjSeq);
                         }
 
                         if (procState > clientProcState) {
@@ -2233,7 +2234,7 @@
                     }
                 }
 
-                conn.trackProcState(clientProcState, mAdjSeq, now);
+                conn.trackProcState(clientProcState, mAdjSeq);
                 if (procState > clientProcState) {
                     procState = clientProcState;
                     state.setCurRawProcState(procState);
@@ -2695,7 +2696,7 @@
             if (!doingAll) {
                 synchronized (mService.mProcessStats.mLock) {
                     mService.setProcessTrackerStateLOSP(app,
-                            mService.mProcessStats.getMemFactorLocked(), now);
+                            mService.mProcessStats.getMemFactorLocked());
                 }
             } else {
                 state.setProcStateChanged(true);
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 4220506..18ad1f5 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -286,6 +286,7 @@
                     && mService.mTraceErrorLogger.isAddErrorIdEnabled()) {
                 errorId = mService.mTraceErrorLogger.generateErrorId();
                 mService.mTraceErrorLogger.addErrorIdToTrace(mApp.processName, errorId);
+                mService.mTraceErrorLogger.addSubjectToTrace(annotation, errorId);
             } else {
                 errorId = null;
             }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 74c35e9..bbd41f7 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -1794,13 +1794,14 @@
         if (app.isPendingStart()) {
             return true;
         }
-        long startTime = SystemClock.uptimeMillis();
+        final long startUptime = SystemClock.uptimeMillis();
+        final long startElapsedTime = SystemClock.elapsedRealtime();
         if (app.getPid() > 0 && app.getPid() != ActivityManagerService.MY_PID) {
-            checkSlow(startTime, "startProcess: removing from pids map");
+            checkSlow(startUptime, "startProcess: removing from pids map");
             mService.removePidLocked(app.getPid(), app);
             app.setBindMountPending(false);
             mService.mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
-            checkSlow(startTime, "startProcess: done removing from pids map");
+            checkSlow(startUptime, "startProcess: done removing from pids map");
             app.setPid(0);
             app.setStartSeq(0);
         }
@@ -1813,9 +1814,9 @@
                 "startProcessLocked removing on hold: " + app);
         mService.mProcessesOnHold.remove(app);
 
-        checkSlow(startTime, "startProcess: starting to update cpu stats");
+        checkSlow(startUptime, "startProcess: starting to update cpu stats");
         mService.updateCpuStats();
-        checkSlow(startTime, "startProcess: done updating cpu stats");
+        checkSlow(startUptime, "startProcess: done updating cpu stats");
 
         try {
             final int userId = UserHandle.getUserId(app.uid);
@@ -1832,7 +1833,7 @@
             if (!app.isolated) {
                 int[] permGids = null;
                 try {
-                    checkSlow(startTime, "startProcess: getting gids from package manager");
+                    checkSlow(startUptime, "startProcess: getting gids from package manager");
                     final IPackageManager pm = AppGlobals.getPackageManager();
                     permGids = pm.getPackageGids(app.info.packageName,
                             MATCH_DIRECT_BOOT_AUTO, app.userId);
@@ -1870,7 +1871,7 @@
                 gids = computeGidsForProcess(mountExternal, uid, permGids, externalStorageAccess);
             }
             app.setMountMode(mountExternal);
-            checkSlow(startTime, "startProcess: building args");
+            checkSlow(startUptime, "startProcess: building args");
             if (mService.mAtmInternal.isFactoryTestProcess(app.getWindowProcessController())) {
                 uid = 0;
             }
@@ -2028,7 +2029,7 @@
 
             return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
                     runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,
-                    instructionSet, invokeWith, startTime);
+                    instructionSet, invokeWith, startUptime, startElapsedTime);
         } catch (RuntimeException e) {
             Slog.e(ActivityManagerService.TAG, "Failure starting process " + app.processName, e);
 
@@ -2048,7 +2049,7 @@
     boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,
             int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,
             String seInfo, String requiredAbi, String instructionSet, String invokeWith,
-            long startTime) {
+            long startUptime, long startElapsedTime) {
         app.setPendingStart(true);
         app.setRemoved(false);
         synchronized (mProcLock) {
@@ -2069,7 +2070,7 @@
         }
         final long startSeq = ++mProcStartSeqCounter;
         app.setStartSeq(startSeq);
-        app.setStartParams(uid, hostingRecord, seInfo, startTime);
+        app.setStartParams(uid, hostingRecord, seInfo, startUptime, startElapsedTime);
         app.setUsingWrapper(invokeWith != null
                 || Zygote.getWrapProperty(app.processName) != null);
         mPendingStarts.put(startSeq, app);
@@ -2086,7 +2087,7 @@
                 final Process.ProcessStartResult startResult = startProcess(hostingRecord,
                         entryPoint, app,
                         uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,
-                        requiredAbi, instructionSet, invokeWith, startTime);
+                        requiredAbi, instructionSet, invokeWith, startUptime);
                 handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
                         startSeq, false);
             } catch (RuntimeException e) {
@@ -5144,7 +5145,8 @@
         }
 
         Watchdog.getInstance().processDied(app.processName, app.getPid());
-        if (app.getDeathRecipient() == null) {
+        if (app.getDeathRecipient() == null
+                && mDyingProcesses.get(app.processName, app.uid) == app) {
             // If we've done unlinkDeathRecipient before calling into this, remove from dying list.
             mDyingProcesses.remove(app.processName, app.uid);
             app.setDyingPid(0);
diff --git a/services/core/java/com/android/server/am/ProcessProfileRecord.java b/services/core/java/com/android/server/am/ProcessProfileRecord.java
index 47573f3..50970b5 100644
--- a/services/core/java/com/android/server/am/ProcessProfileRecord.java
+++ b/services/core/java/com/android/server/am/ProcessProfileRecord.java
@@ -518,12 +518,13 @@
         }
     }
 
-    void setProcessTrackerState(int procState, int memFactor, long now) {
+    void setProcessTrackerState(int procState, int memFactor) {
         synchronized (mService.mProcessStats.mLock) {
             final ProcessState tracker = mBaseProcessTracker;
             if (tracker != null) {
                 if (procState != PROCESS_STATE_NONEXISTENT) {
                     final PackageList pkgList = mApp.getPkgList();
+                    final long now = SystemClock.uptimeMillis();
                     synchronized (pkgList) {
                         tracker.setState(procState, memFactor, now,
                                 pkgList.getPackageListLocked());
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 8ae1259..eba02f10 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -26,7 +26,6 @@
 import android.app.ApplicationExitInfo.Reason;
 import android.app.ApplicationExitInfo.SubReason;
 import android.app.IApplicationThread;
-import android.app.RemoteServiceException;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ProcessInfo;
 import android.content.pm.VersionedPackage;
@@ -178,9 +177,14 @@
     private volatile String mSeInfo;
 
     /**
-     * When the process is started.
+     * When the process is started. (before zygote fork)
      */
-    private volatile long mStartTime;
+    private volatile long mStartUptime;
+
+    /**
+     * When the process is started. (before zygote fork)
+     */
+    private volatile long mStartElapsedTime;
 
     /**
      * This will be same as {@link #uid} usually except for some apps used during factory testing.
@@ -372,16 +376,18 @@
     Runnable mSuccessorStartRunnable;
 
     void setStartParams(int startUid, HostingRecord hostingRecord, String seInfo,
-            long startTime) {
+            long startUptime, long startElapsedTime) {
         this.mStartUid = startUid;
         this.mHostingRecord = hostingRecord;
         this.mSeInfo = seInfo;
-        this.mStartTime = startTime;
+        this.mStartUptime = startUptime;
+        this.mStartElapsedTime = startElapsedTime;
     }
 
     @GuardedBy({"mService", "mProcLock"})
     void dump(PrintWriter pw, String prefix) {
         final long nowUptime = SystemClock.uptimeMillis();
+        final long nowElapsedTime = SystemClock.elapsedRealtime();
 
         pw.print(prefix); pw.print("user #"); pw.print(userId);
                 pw.print(" uid="); pw.print(info.uid);
@@ -442,6 +448,10 @@
         pw.print(prefix); pw.print("pid="); pw.println(mPid);
         pw.print(prefix); pw.print("lastActivityTime=");
         TimeUtils.formatDuration(mLastActivityTime, nowUptime, pw);
+        pw.print(prefix); pw.print("startUptimeTime=");
+        TimeUtils.formatDuration(mStartElapsedTime, nowUptime, pw);
+        pw.print(prefix); pw.print("startElapsedTime=");
+        TimeUtils.formatDuration(mStartElapsedTime, nowElapsedTime, pw);
         pw.println();
         if (mPersistent || mRemoved) {
             pw.print(prefix); pw.print("persistent="); pw.print(mPersistent);
@@ -671,12 +681,21 @@
         mSeInfo = seInfo;
     }
 
-    long getStartTime() {
-        return mStartTime;
+    long getStartUptime() {
+        return mStartUptime;
     }
 
-    void setStartTime(long startTime) {
-        mStartTime = startTime;
+    /**
+     * Same as {@link #getStartUptime()}.
+     * @deprecated use {@link #getStartUptime()} instead for clarity.
+     */
+    @Deprecated
+    long getStartTime() {
+        return mStartUptime;
+    }
+
+    long getStartElapsedTime() {
+        return mStartElapsedTime;
     }
 
     int getStartUid() {
@@ -955,11 +974,6 @@
         return mServices.hasForegroundServices();
     }
 
-    @GuardedBy("mService")
-    void scheduleCrashLocked(String message) {
-        scheduleCrashLocked(message, RemoteServiceException.TYPE_ID);
-    }
-
     /**
      * Let an app process throw an exception on a binder thread, which typically crashes the
      * process, unless it has an unhandled exception handler.
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 91ee4eb..9b731d5 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -28,6 +28,7 @@
 import android.app.IApplicationThread;
 import android.app.Notification;
 import android.app.PendingIntent;
+import android.app.RemoteServiceException.CannotPostForegroundServiceNotificationException;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -1059,7 +1060,8 @@
                         // If it gave us a garbage notification, it doesn't
                         // get to be foreground.
                         ams.mServices.killMisbehavingService(record,
-                                appUid, appPid, localPackageName);
+                                appUid, appPid, localPackageName,
+                                CannotPostForegroundServiceNotificationException.TYPE_ID);
                     }
                 }
             });
diff --git a/services/core/java/com/android/server/am/TraceErrorLogger.java b/services/core/java/com/android/server/am/TraceErrorLogger.java
index c658100..29a9b5c 100644
--- a/services/core/java/com/android/server/am/TraceErrorLogger.java
+++ b/services/core/java/com/android/server/am/TraceErrorLogger.java
@@ -54,4 +54,17 @@
                 COUNTER_PREFIX + processName + "#" + errorId.toString(),
                 PLACEHOLDER_VALUE);
     }
+
+    /**
+     * Pushes a counter containing an ANR/Watchdog subject and a unique id so that the subject
+     * can be uniquely identified.
+     *
+     * @param subject The subject to include in the trace.
+     * @param errorId The unique id with which to tag the trace.
+     */
+    public void addSubjectToTrace(String subject, UUID errorId) {
+        Trace.traceCounter(Trace.TRACE_TAG_ACTIVITY_MANAGER,
+                String.format("Subject(for ErrorId %s):%s", errorId.toString(), subject),
+                PLACEHOLDER_VALUE);
+    }
 }
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index a075a13..e79cba1 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -67,10 +67,10 @@
 import android.content.PermissionChecker;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackagePartitions;
 import android.content.pm.UserInfo;
 import android.os.BatteryStats;
 import android.os.Binder;
-import android.os.Build;
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Handler;
@@ -103,6 +103,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.IKeyguardDismissCallback;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.internal.widget.LockPatternUtils;
@@ -162,6 +163,7 @@
     static final int USER_UNLOCKED_MSG = 105;
     static final int REPORT_LOCKED_BOOT_COMPLETE_MSG = 110;
     static final int START_USER_SWITCH_FG_MSG = 120;
+    static final int COMPLETE_USER_SWITCH_MSG = 130;
 
     // Message constant to clear {@link UserJourneySession} from {@link mUserIdToUserJourneyMap} if
     // the user journey, defined in the UserLifecycleJourneyReported atom for statsd, is not
@@ -385,6 +387,7 @@
     @VisibleForTesting
     UserController(Injector injector) {
         mInjector = injector;
+        // This should be called early to avoid a null mHandler inside the injector
         mHandler = mInjector.getHandler(this);
         mUiHandler = mInjector.getUiHandler(this);
         // User 0 is the first and only user that runs at boot.
@@ -716,7 +719,7 @@
         // purposefully block sending BOOT_COMPLETED until after all
         // PRE_BOOT receivers are finished to avoid ANR'ing apps
         final UserInfo info = getUserInfo(userId);
-        if (!Objects.equals(info.lastLoggedInFingerprint, Build.FINGERPRINT)
+        if (!Objects.equals(info.lastLoggedInFingerprint, PackagePartitions.FINGERPRINT)
                 || SystemProperties.getBoolean("persist.pm.mock-upgrade", false)) {
             // Suppress double notifications for managed profiles that
             // were unlocked automatically as part of their parent user
@@ -1535,7 +1538,10 @@
                 // with the option to show the user switcher on the keyguard.
                 if (userSwitchUiEnabled) {
                     mInjector.getWindowManager().setSwitchingUser(true);
-                    mInjector.getWindowManager().lockNow(null);
+                    // Only lock if the user has a secure keyguard PIN/Pattern/Pwd
+                    if (mInjector.getKeyguardManager().isDeviceSecure(userId)) {
+                        mInjector.getWindowManager().lockNow(null);
+                    }
                 }
             } else {
                 final Integer currentUserIdInt = mCurrentUserId;
@@ -1803,7 +1809,8 @@
     private void showUserSwitchDialog(Pair<UserInfo, UserInfo> fromToUserPair) {
         // The dialog will show and then initiate the user switch by calling startUserInForeground
         mInjector.showUserSwitchingDialog(fromToUserPair.first, fromToUserPair.second,
-                getSwitchingFromSystemUserMessage(), getSwitchingToSystemUserMessage());
+                getSwitchingFromSystemUserMessageUnchecked(),
+                getSwitchingToSystemUserMessageUnchecked());
     }
 
     private void dispatchForegroundProfileChanged(@UserIdInt int userId) {
@@ -1967,11 +1974,10 @@
 
         EventLog.writeEvent(EventLogTags.UC_CONTINUE_USER_SWITCH, oldUserId, newUserId);
 
-        if (isUserSwitchUiEnabled()) {
-            t.traceBegin("stopFreezingScreen");
-            mInjector.getWindowManager().stopFreezingScreen();
-            t.traceEnd();
-        }
+        // Do the keyguard dismiss and unfreeze later
+        mHandler.removeMessages(COMPLETE_USER_SWITCH_MSG);
+        mHandler.sendMessage(mHandler.obtainMessage(COMPLETE_USER_SWITCH_MSG, newUserId, 0));
+
         uss.switching = false;
         mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
         mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_COMPLETE_MSG, newUserId, 0));
@@ -1981,6 +1987,34 @@
         t.traceEnd(); // end continueUserSwitch
     }
 
+    @VisibleForTesting
+    void completeUserSwitch(int newUserId) {
+        if (isUserSwitchUiEnabled()) {
+            // If there is no challenge set, dismiss the keyguard right away
+            if (!mInjector.getKeyguardManager().isDeviceSecure(newUserId)) {
+                // Wait until the keyguard is dismissed to unfreeze
+                mInjector.dismissKeyguard(
+                        new Runnable() {
+                            public void run() {
+                                unfreezeScreen();
+                            }
+                        },
+                        "User Switch");
+                return;
+            } else {
+                unfreezeScreen();
+            }
+        }
+    }
+
+    @VisibleForTesting
+    void unfreezeScreen() {
+        TimingsTraceAndSlog t = new TimingsTraceAndSlog();
+        t.traceBegin("stopFreezingScreen");
+        mInjector.getWindowManager().stopFreezingScreen();
+        t.traceEnd();
+    }
+
     private void moveUserToForeground(UserState uss, int oldUserId, int newUserId) {
         boolean homeInFront = mInjector.taskSupervisorSwitchUser(newUserId, uss);
         if (homeInFront) {
@@ -2589,18 +2623,40 @@
         }
     }
 
-    private String getSwitchingFromSystemUserMessage() {
+    // Called by AMS, must check permission
+    String getSwitchingFromSystemUserMessage() {
+        checkHasManageUsersPermission("getSwitchingFromSystemUserMessage()");
+
+        return getSwitchingFromSystemUserMessageUnchecked();
+    }
+
+    // Called by AMS, must check permission
+    String getSwitchingToSystemUserMessage() {
+        checkHasManageUsersPermission("getSwitchingToSystemUserMessage()");
+
+        return getSwitchingToSystemUserMessageUnchecked();
+    }
+
+    private String getSwitchingFromSystemUserMessageUnchecked() {
         synchronized (mLock) {
             return mSwitchingFromSystemUserMessage;
         }
     }
 
-    private String getSwitchingToSystemUserMessage() {
+    private String getSwitchingToSystemUserMessageUnchecked() {
         synchronized (mLock) {
             return mSwitchingToSystemUserMessage;
         }
     }
 
+    private void checkHasManageUsersPermission(String operation) {
+        if (mInjector.checkCallingPermission(
+                android.Manifest.permission.MANAGE_USERS) == PackageManager.PERMISSION_DENIED) {
+            throw new SecurityException(
+                    "You need MANAGE_USERS permission to call " + operation);
+        }
+    }
+
     void dumpDebug(ProtoOutputStream proto, long fieldId) {
         synchronized (mLock) {
             long token = proto.start(fieldId);
@@ -2673,6 +2729,12 @@
             pw.println("  mMaxRunningUsers:" + mMaxRunningUsers);
             pw.println("  mUserSwitchUiEnabled:" + mUserSwitchUiEnabled);
             pw.println("  mInitialized:" + mInitialized);
+            if (mSwitchingFromSystemUserMessage != null) {
+                pw.println("  mSwitchingFromSystemUserMessage: " + mSwitchingFromSystemUserMessage);
+            }
+            if (mSwitchingToSystemUserMessage != null) {
+                pw.println("  mSwitchingToSystemUserMessage: " + mSwitchingToSystemUserMessage);
+            }
         }
     }
 
@@ -2772,6 +2834,9 @@
             case CLEAR_USER_JOURNEY_SESSION_MSG:
                 logAndClearSessionId(msg.arg1);
                 break;
+            case COMPLETE_USER_SWITCH_MSG:
+                completeUserSwitch(msg.arg1);
+                break;
         }
         return false;
     }
@@ -2961,13 +3026,14 @@
         private final ActivityManagerService mService;
         private UserManagerService mUserManager;
         private UserManagerInternal mUserManagerInternal;
+        private Handler mHandler;
 
         Injector(ActivityManagerService service) {
             mService = service;
         }
 
         protected Handler getHandler(Handler.Callback callback) {
-            return new Handler(mService.mHandlerThread.getLooper(), callback);
+            return mHandler = new Handler(mService.mHandlerThread.getLooper(), callback);
         }
 
         protected Handler getUiHandler(Handler.Callback callback) {
@@ -3165,5 +3231,24 @@
         protected IStorageManager getStorageManager() {
             return IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
         }
+
+        protected void dismissKeyguard(Runnable runnable, String reason) {
+            getWindowManager().dismissKeyguard(new IKeyguardDismissCallback.Stub() {
+                @Override
+                public void onDismissError() throws RemoteException {
+                    mHandler.post(runnable);
+                }
+
+                @Override
+                public void onDismissSucceeded() throws RemoteException {
+                    mHandler.post(runnable);
+                }
+
+                @Override
+                public void onDismissCancelled() throws RemoteException {
+                    mHandler.post(runnable);
+                }
+            }, reason);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/app/OWNERS b/services/core/java/com/android/server/app/OWNERS
new file mode 100644
index 0000000..aaebbfa
--- /dev/null
+++ b/services/core/java/com/android/server/app/OWNERS
@@ -0,0 +1 @@
+per-file GameManager* = file:/GAME_MANAGER_OWNERS
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4dd1682..0f3b082 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -133,6 +133,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.os.VibratorManager;
@@ -550,10 +551,8 @@
     private final boolean mHasVibrator;
     // Used to play vibrations
     private Vibrator mVibrator;
-    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-            .build();
+    private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
+            VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
 
     // Broadcast receiver for device connections intent broadcasts
     private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
@@ -4343,7 +4342,7 @@
             return false;
         }
         mVibrator.vibrate(Binder.getCallingUid(), mContext.getOpPackageName(), effect,
-                reason, VIBRATION_ATTRIBUTES);
+                reason, TOUCH_VIBRATION_ATTRIBUTES);
         return true;
     }
 
@@ -4638,12 +4637,13 @@
          * or recording for VOICE_COMMUNICATION.
          *   or
          * - It requests a mode different from MODE_IN_COMMUNICATION or MODE_NORMAL
+         * Note: only privileged apps can request MODE_IN_CALL, MODE_CALL_REDIRECT
+         * or MODE_COMMUNICATION_REDIRECT.
          */
         public boolean isActive() {
             return mIsPrivileged
                     || ((mMode == AudioSystem.MODE_IN_COMMUNICATION)
                         && (mRecordingActive || mPlaybackActive))
-                    || mMode == AudioSystem.MODE_IN_CALL
                     || mMode == AudioSystem.MODE_RINGTONE
                     || mMode == AudioSystem.MODE_CALL_SCREENING;
         }
@@ -4752,9 +4752,13 @@
         final boolean hasModifyPhoneStatePermission = mContext.checkCallingOrSelfPermission(
                 android.Manifest.permission.MODIFY_PHONE_STATE)
                 == PackageManager.PERMISSION_GRANTED;
-        if ((mode == AudioSystem.MODE_IN_CALL) && !hasModifyPhoneStatePermission) {
-            Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
-                    + pid + ", uid=" + Binder.getCallingUid());
+        if ((mode == AudioSystem.MODE_IN_CALL
+                || mode == AudioSystem.MODE_CALL_REDIRECT
+                || mode == AudioSystem.MODE_COMMUNICATION_REDIRECT)
+                && !hasModifyPhoneStatePermission) {
+            Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode("
+                    + AudioSystem.modeToString(mode) + ") from pid=" + pid
+                    + ", uid=" + Binder.getCallingUid());
             return;
         }
 
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 c2eb062..2465ec5 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
@@ -19,12 +19,12 @@
 import android.annotation.NonNull;
 import android.content.Context;
 import android.hardware.biometrics.BiometricConstants;
-import android.media.AudioAttributes;
 import android.os.IBinder;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.util.Slog;
@@ -38,11 +38,8 @@
 
     private static final String TAG = "Biometrics/AcquisitionClient";
 
-    private static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
-            new AudioAttributes.Builder()
-                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-                    .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-                    .build();
+    private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
+            VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
 
     private static final VibrationEffect SUCCESS_VIBRATION_EFFECT =
             VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
@@ -199,7 +196,7 @@
                     getContext().getOpPackageName(),
                     SUCCESS_VIBRATION_EFFECT,
                     getClass().getSimpleName() + "::success",
-                    VIBRATION_SONIFICATION_ATTRIBUTES);
+                    TOUCH_VIBRATION_ATTRIBUTES);
         }
     }
 
@@ -210,7 +207,7 @@
                     getContext().getOpPackageName(),
                     ERROR_VIBRATION_EFFECT,
                     getClass().getSimpleName() + "::error",
-                    VIBRATION_SONIFICATION_ATTRIBUTES);
+                    TOUCH_VIBRATION_ATTRIBUTES);
         }
     }
 }
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 61b8ded..7341e74 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -251,7 +251,7 @@
                         "Successful background authentication!");
             }
 
-            mAlreadyDone = true;
+            markAlreadyDone();
 
             if (mTaskStackListener != null) {
                 mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
@@ -327,7 +327,7 @@
             final @LockoutTracker.LockoutMode int lockoutMode =
                     handleFailedAttempt(getTargetUserId());
             if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
-                mAlreadyDone = true;
+                markAlreadyDone();
             }
 
             final CoexCoordinator coordinator = CoexCoordinator.getInstance();
diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
index 9764a16..b73e911 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
@@ -114,7 +114,7 @@
     // Currently only used for authentication client. The cookie generated by BiometricService
     // is never 0.
     private final int mCookie;
-    boolean mAlreadyDone;
+    private boolean mAlreadyDone = false;
 
     // Use an empty callback by default since delayed operations can receive events
     // before they are started and cause NPE in subclasses that access this field directly.
@@ -202,11 +202,9 @@
         return callback;
     }
 
-    public boolean isAlreadyDone() {
-        return mAlreadyDone;
-    }
-
-    public void destroy() {
+    /** Signals this operation has completed its lifecycle and should no longer be used. */
+    void destroy() {
+        mAlreadyDone = true;
         if (mToken != null) {
             try {
                 mToken.unlinkToDeath(this, 0);
@@ -218,6 +216,20 @@
         }
     }
 
+    /**
+     * Call while the operation is still active, but nearly done, to prevent any action
+     * upon client death (only needed for authentication clients).
+     */
+    void markAlreadyDone() {
+        Slog.d(TAG, "marking operation as done: " + this);
+        mAlreadyDone = true;
+    }
+
+    /** If this operation has been marked as completely done (or cancelled). */
+    public boolean isAlreadyDone() {
+        return mAlreadyDone;
+    }
+
     @Override
     public void binderDied() {
         binderDiedInternal(true /* clearListener */);
@@ -225,10 +237,9 @@
 
     // TODO(b/157790417): Move this to the scheduler
     void binderDiedInternal(boolean clearListener) {
-        Slog.e(TAG, "Binder died, owner: " + getOwnerString()
-                + ", operation: " + this.getClass().getName());
+        Slog.e(TAG, "Binder died, operation: " + this);
 
-        if (isAlreadyDone()) {
+        if (mAlreadyDone) {
             Slog.w(TAG, "Binder died but client is finished, ignoring");
             return;
         }
@@ -299,7 +310,7 @@
     @Override
     public String toString() {
         return "{[" + mSequentialId + "] "
-                + this.getClass().getSimpleName()
+                + this.getClass().getName()
                 + ", proto=" + getProtoEnum()
                 + ", owner=" + getOwnerString()
                 + ", cookie=" + getCookie()
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 361ec40..a358bc2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java
@@ -605,6 +605,9 @@
         if (operation.mState == Operation.STATE_WAITING_FOR_COOKIE) {
             Slog.w(getTag(), "Skipping cancellation for non-started operation: " + operation);
             // We can set it to null immediately, since the HAL was never notified to start.
+            if (mCurrentOperation != null) {
+                mCurrentOperation.mClientMonitor.destroy();
+            }
             mCurrentOperation = null;
             startNextOperationIfIdle();
             return;
diff --git a/services/core/java/com/android/server/communal/CommunalManagerService.java b/services/core/java/com/android/server/communal/CommunalManagerService.java
index b506230..1196442 100644
--- a/services/core/java/com/android/server/communal/CommunalManagerService.java
+++ b/services/core/java/com/android/server/communal/CommunalManagerService.java
@@ -17,6 +17,8 @@
 package com.android.server.communal;
 
 import static android.app.ActivityManager.INTENT_SENDER_ACTIVITY;
+import static android.app.communal.CommunalManager.ALLOW_COMMUNAL_MODE_BY_DEFAULT;
+import static android.app.communal.CommunalManager.ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT;
 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
 
 import static com.android.server.wm.ActivityInterceptorCallback.COMMUNAL_MODE_ORDERED_ID;
@@ -25,14 +27,10 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
-import android.annotation.TestApi;
 import android.app.KeyguardManager;
 import android.app.PendingIntent;
 import android.app.communal.ICommunalManager;
 import android.app.compat.CompatChanges;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.Disabled;
-import android.compat.annotation.Overridable;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -80,29 +78,6 @@
     private final PackageManager mPackageManager;
     private final DreamManagerInternal mDreamManagerInternal;
 
-    /**
-     * This change id is used to annotate packages which are allowed to run in communal mode.
-     *
-     * @hide
-     */
-    @ChangeId
-    @Overridable
-    @Disabled
-    @TestApi
-    public static final long ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT = 200324021L;
-
-    /**
-     * This change id is used to annotate packages which can run in communal mode by default,
-     * without requiring user opt-in.
-     *
-     * @hide
-     */
-    @ChangeId
-    @Overridable
-    @Disabled
-    @TestApi
-    public static final long ALLOW_COMMUNAL_MODE_BY_DEFAULT = 203673428L;
-
     private final ActivityInterceptorCallback mActivityInterceptorCallback =
             new ActivityInterceptorCallback() {
                 @Nullable
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index fb74170..e2e56ae 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -223,11 +223,18 @@
      * Overrides the enabled state for a given change and app.
      *
      *
-     * @param overrides   list of overrides to default changes config.
-     * @param packageName app for which the overrides will be applied.
+     * @param overrides            list of overrides to default changes config.
+     * @param packageName          app for which the overrides will be applied.
+     * @param skipUnknownChangeIds whether to skip unknown change IDs in {@code overrides}.
      */
-    synchronized void addOverrides(CompatibilityOverrideConfig overrides, String packageName) {
+    synchronized void addPackageOverrides(CompatibilityOverrideConfig overrides,
+            String packageName, boolean skipUnknownChangeIds) {
         for (Long changeId : overrides.overrides.keySet()) {
+            if (skipUnknownChangeIds && !isKnownChangeId(changeId)) {
+                Slog.w(TAG, "Trying to add overrides for unknown Change ID " + changeId + ". "
+                        + "Skipping Change ID.");
+                continue;
+            }
             addOverrideUnsafe(changeId, packageName, overrides.overrides.get(changeId));
         }
         saveOverrides();
@@ -338,7 +345,8 @@
 
     /**
      * Removes all overrides previously added via {@link #addOverride(long, String, boolean)} or
-     * {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package.
+     * {@link #addPackageOverrides(CompatibilityOverrideConfig, String, boolean)} for a certain
+     * package.
      *
      * <p>This restores the default behaviour for the given app.
      *
@@ -359,7 +367,8 @@
     /**
      * Removes overrides whose change ID is specified in {@code overridesToRemove} that were
      * previously added via {@link #addOverride(long, String, boolean)} or
-     * {@link #addOverrides(CompatibilityOverrideConfig, String)} for a certain package.
+     * {@link #addPackageOverrides(CompatibilityOverrideConfig, String, boolean)} for a certain
+     * package.
      *
      * <p>This restores the default behaviour for the given change IDs and app.
      *
@@ -370,6 +379,11 @@
             String packageName) {
         boolean shouldInvalidateCache = false;
         for (Long changeId : overridesToRemove.changeIds) {
+            if (!isKnownChangeId(changeId)) {
+                Slog.w(TAG, "Trying to remove overrides for unknown Change ID " + changeId + ". "
+                        + "Skipping Change ID.");
+                continue;
+            }
             shouldInvalidateCache |= removeOverrideUnsafe(changeId, packageName);
         }
         if (shouldInvalidateCache) {
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index b32d1d7..6ea89d4 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -205,7 +205,8 @@
             overridesMap.put(change, new PackageOverride.Builder().setEnabled(false)
                     .build());
         }
-        mCompatConfig.addOverrides(new CompatibilityOverrideConfig(overridesMap), packageName);
+        mCompatConfig.addPackageOverrides(new CompatibilityOverrideConfig(overridesMap),
+                packageName, /* skipUnknownChangeIds */ false);
         killPackage(packageName);
     }
 
@@ -220,7 +221,8 @@
             overridesMap.put(change, new PackageOverride.Builder().setEnabled(false)
                     .build());
         }
-        mCompatConfig.addOverrides(new CompatibilityOverrideConfig(overridesMap), packageName);
+        mCompatConfig.addPackageOverrides(new CompatibilityOverrideConfig(overridesMap),
+                packageName, /* skipUnknownChangeIds */ false);
     }
 
     @Override
@@ -229,7 +231,7 @@
         // TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
         checkCompatChangeOverrideOverridablePermission();
         checkAllCompatOverridesAreOverridable(overrides.overrides.keySet());
-        mCompatConfig.addOverrides(overrides, packageName);
+        mCompatConfig.addPackageOverrides(overrides, packageName, /* skipUnknownChangeIds= */ true);
     }
 
     @Override
@@ -435,7 +437,7 @@
 
     private void checkAllCompatOverridesAreOverridable(Collection<Long> changeIds) {
         for (Long changeId : changeIds) {
-            if (!mCompatConfig.isOverridable(changeId)) {
+            if (isKnownChangeId(changeId) && !mCompatConfig.isOverridable(changeId)) {
                 throw new SecurityException("Only change ids marked as Overridable can be "
                         + "overridden.");
             }
diff --git a/services/core/java/com/android/server/connectivity/OWNERS b/services/core/java/com/android/server/connectivity/OWNERS
index 7311eee..62c5737 100644
--- a/services/core/java/com/android/server/connectivity/OWNERS
+++ b/services/core/java/com/android/server/connectivity/OWNERS
@@ -1,8 +1,2 @@
 set noparent
-
-codewiz@google.com
-ek@google.com
-jchalard@google.com
-lorenzo@google.com
-reminv@google.com
-satk@google.com
+file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking
diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
index cb2cd14..e9af6011 100644
--- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java
+++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java
@@ -220,13 +220,13 @@
             float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
             long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
             boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
-            HysteresisLevels screenBrightnessThresholds, LogicalDisplay display, Context context,
+            HysteresisLevels screenBrightnessThresholds, Context context,
             HighBrightnessModeController hbmController) {
         this(new Injector(), callbacks, looper, sensorManager, lightSensor, mapper,
                 lightSensorWarmUpTime, brightnessMin, brightnessMax, dozeScaleFactor,
                 lightSensorRate, initialLightSensorRate, brighteningLightDebounceConfig,
                 darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig,
-                ambientBrightnessThresholds, screenBrightnessThresholds, display, context,
+                ambientBrightnessThresholds, screenBrightnessThresholds, context,
                 hbmController
         );
     }
@@ -238,7 +238,7 @@
             float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate,
             long brighteningLightDebounceConfig, long darkeningLightDebounceConfig,
             boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds,
-            HysteresisLevels screenBrightnessThresholds, LogicalDisplay display, Context context,
+            HysteresisLevels screenBrightnessThresholds, Context context,
             HighBrightnessModeController hbmController) {
         mInjector = injector;
         mContext = context;
diff --git a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
index 74a21a7..beb4d5b 100644
--- a/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
+++ b/services/core/java/com/android/server/display/BrightnessMappingStrategy.java
@@ -60,17 +60,62 @@
 
     private static final Plog PLOG = Plog.createSystemPlog(TAG);
 
+    /**
+     * Creates a BrightnessMappingStrategy for active (normal) mode.
+     * @param resources
+     * @param displayDeviceConfig
+     * @return the BrightnessMappingStrategy
+     */
     @Nullable
     public static BrightnessMappingStrategy create(Resources resources,
             DisplayDeviceConfig displayDeviceConfig) {
+        return create(resources, displayDeviceConfig, /* isForIdleMode= */ false);
+    }
 
-        // Display independent values
-        float[] luxLevels = getLuxLevels(resources.getIntArray(
-                com.android.internal.R.array.config_autoBrightnessLevels));
+    /**
+     * Creates a BrightnessMappingStrategy for idle screen brightness mode.
+     * @param resources
+     * @param displayDeviceConfig
+     * @return the BrightnessMappingStrategy
+     */
+    @Nullable
+    public static BrightnessMappingStrategy createForIdleMode(Resources resources,
+            DisplayDeviceConfig displayDeviceConfig) {
+        return create(resources, displayDeviceConfig, /* isForIdleMode= */ true);
+    }
+
+    /**
+     * Creates a BrightnessMapping strategy for either active or idle screen brightness mode.
+     * We do not create a simple mapping strategy for idle mode.
+     *
+     * @param resources
+     * @param displayDeviceConfig
+     * @param isForIdleMode determines whether the configurations loaded are for idle screen
+     *                      brightness mode or active screen brightness mode.
+     * @return the BrightnessMappingStrategy
+     */
+    @Nullable
+    private static BrightnessMappingStrategy create(Resources resources,
+            DisplayDeviceConfig displayDeviceConfig, boolean isForIdleMode) {
+
+        // Display independent, mode dependent values
+        float[] brightnessLevelsNits;
+        float[] luxLevels;
+        if (isForIdleMode) {
+            brightnessLevelsNits = getFloatArray(resources.obtainTypedArray(
+                    com.android.internal.R.array.config_autoBrightnessDisplayValuesNitsIdle));
+            luxLevels = getLuxLevels(resources.getIntArray(
+                    com.android.internal.R.array.config_autoBrightnessLevelsIdle));
+        } else {
+            brightnessLevelsNits = getFloatArray(resources.obtainTypedArray(
+                    com.android.internal.R.array.config_autoBrightnessDisplayValuesNits));
+            luxLevels = getLuxLevels(resources.getIntArray(
+                    com.android.internal.R.array.config_autoBrightnessLevels));
+        }
+
+        // Display independent, mode independent values
         int[] brightnessLevelsBacklight = resources.getIntArray(
                 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
-        float[] brightnessLevelsNits = getFloatArray(resources.obtainTypedArray(
-                com.android.internal.R.array.config_autoBrightnessDisplayValuesNits));
         float autoBrightnessAdjustmentMaxGamma = resources.getFraction(
                 com.android.internal.R.fraction.config_autoBrightnessAdjustmentMaxGamma,
                 1, 1);
@@ -91,7 +136,7 @@
             builder.setShortTermModelUpperLuxMultiplier(SHORT_TERM_MODEL_THRESHOLD_RATIO);
             return new PhysicalMappingStrategy(builder.build(), nitsRange, brightnessRange,
                     autoBrightnessAdjustmentMaxGamma);
-        } else if (isValidMapping(luxLevels, brightnessLevelsBacklight)) {
+        } else if (isValidMapping(luxLevels, brightnessLevelsBacklight) && !isForIdleMode) {
             return new SimpleMappingStrategy(luxLevels, brightnessLevelsBacklight,
                     autoBrightnessAdjustmentMaxGamma, shortTermModelTimeout);
         } else {
diff --git a/services/core/java/com/android/server/display/DensityMap.java b/services/core/java/com/android/server/display/DensityMap.java
new file mode 100644
index 0000000..4aafd14
--- /dev/null
+++ b/services/core/java/com/android/server/display/DensityMap.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2021 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.display;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * Class which can compute the logical density for a display resolution. It holds a collection
+ * of pre-configured densities, which are used for look-up and interpolation.
+ */
+public class DensityMap {
+
+    // Instead of resolutions we store the squared diagonal size. Diagonals make the map
+    // keys invariant to rotations and are useful for interpolation because they're scalars.
+    // Squared diagonals have the same properties as diagonals (the square function is monotonic)
+    // but also allow us to use integer types and avoid floating point arithmetics.
+    private final Entry[] mSortedDensityMapEntries;
+
+    /**
+     * Creates a density map. The newly created object takes ownership of the passed array.
+     */
+    static DensityMap createByOwning(Entry[] densityMapEntries) {
+        return new DensityMap(densityMapEntries);
+    }
+
+    private DensityMap(Entry[] densityMapEntries) {
+        Arrays.sort(densityMapEntries, Comparator.comparingInt(entry -> entry.squaredDiagonal));
+        mSortedDensityMapEntries = densityMapEntries;
+        verifyDensityMap(mSortedDensityMapEntries);
+    }
+
+    /**
+     * Returns the logical density for the given resolution.
+     *
+     * If the resolution matches one of the entries in the map, the corresponding density is
+     * returned. Otherwise the return value is interpolated using the closest entries in the map.
+     */
+    public int getDensityForResolution(int width, int height) {
+        int squaredDiagonal = width * width + height * height;
+
+        // Search for two pre-configured entries "left" and "right" with the following criteria
+        //  * left <= squaredDiagonal
+        //  * squaredDiagonal - left is minimal
+        //  * right > squaredDiagonal
+        //  * right - squaredDiagonal is minimal
+        Entry left = Entry.ZEROES;
+        Entry right = null;
+
+        for (Entry entry : mSortedDensityMapEntries) {
+            if (entry.squaredDiagonal <= squaredDiagonal) {
+                left = entry;
+            } else {
+                right = entry;
+                break;
+            }
+        }
+
+        // Check if we found an exact match.
+        if (left.squaredDiagonal == squaredDiagonal) {
+            return left.density;
+        }
+
+        // If no configured resolution is higher than the specified resolution, interpolate
+        // between (0,0) and (maxConfiguredDiagonal, maxConfiguredDensity).
+        if (right == null) {
+            right = left;  // largest entry in the sorted array
+            left = Entry.ZEROES;
+        }
+
+        double leftDiagonal = Math.sqrt(left.squaredDiagonal);
+        double rightDiagonal = Math.sqrt(right.squaredDiagonal);
+        double diagonal = Math.sqrt(squaredDiagonal);
+
+        return (int) Math.round((diagonal - leftDiagonal) * (right.density - left.density)
+                / (rightDiagonal - leftDiagonal) + left.density);
+    }
+
+    private static void verifyDensityMap(Entry[] sortedEntries) {
+        for (int i = 1; i < sortedEntries.length; i++) {
+            Entry prev = sortedEntries[i - 1];
+            Entry curr = sortedEntries[i];
+
+            if (prev.squaredDiagonal == curr.squaredDiagonal) {
+                // This will most often happen because there are two entries with the same
+                // resolution (AxB and AxB) or rotated resolution (AxB and BxA), but it can also
+                // happen in the very rare cases when two different resolutions happen to have
+                // the same diagonal (e.g. 100x700 and 500x500).
+                throw new IllegalStateException("Found two entries in the density map with"
+                        + " the same diagonal: " + prev + ", " + curr);
+            } else if (prev.density > curr.density) {
+                throw new IllegalStateException("Found two entries in the density map with"
+                        + " increasing diagonal but decreasing density: " + prev + ", " + curr);
+            }
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "DensityMap{"
+                + "mDensityMapEntries=" + Arrays.toString(mSortedDensityMapEntries)
+                + '}';
+    }
+
+    static class Entry {
+        public static final Entry ZEROES = new Entry(0, 0, 0);
+
+        public final int squaredDiagonal;
+        public final int density;
+
+        Entry(int width, int height, int density) {
+            this.squaredDiagonal = width * width + height * height;
+            this.density = density;
+        }
+
+        @Override
+        public String toString() {
+            return "DensityMapEntry{"
+                    + "squaredDiagonal=" + squaredDiagonal
+                    + ", density=" + density + '}';
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 2ae5cbb..a9e1647 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
+import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.hardware.display.DisplayManagerInternal;
 import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
@@ -31,6 +32,7 @@
 
 import com.android.internal.R;
 import com.android.internal.display.BrightnessSynchronizer;
+import com.android.server.display.config.Density;
 import com.android.server.display.config.DisplayConfiguration;
 import com.android.server.display.config.DisplayQuirks;
 import com.android.server.display.config.HbmTiming;
@@ -52,6 +54,7 @@
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 
 import javax.xml.datatype.DatatypeConfigurationException;
@@ -70,6 +73,8 @@
     private static final String ETC_DIR = "etc";
     private static final String DISPLAY_CONFIG_DIR = "displayconfig";
     private static final String CONFIG_FILE_FORMAT = "display_%s.xml";
+    private static final String DEFAULT_CONFIG_FILE = "default.xml";
+    private static final String DEFAULT_CONFIG_FILE_WITH_UIMODE_FORMAT = "default_%s.xml";
     private static final String PORT_SUFFIX_FORMAT = "port_%d";
     private static final String STABLE_ID_SUFFIX_FORMAT = "id_%d";
     private static final String NO_SUFFIX_FORMAT = "%d";
@@ -121,6 +126,7 @@
     private List<String> mQuirks;
     private boolean mIsHighBrightnessModeEnabled = false;
     private HighBrightnessModeData mHbmData;
+    private DensityMap mDensityMap;
     private String mLoadedFrom = null;
 
     private DisplayDeviceConfig(Context context) {
@@ -141,6 +147,33 @@
      */
     public static DisplayDeviceConfig create(Context context, long physicalDisplayId,
             boolean isDefaultDisplay) {
+        final DisplayDeviceConfig config = createWithoutDefaultValues(context, physicalDisplayId,
+                isDefaultDisplay);
+
+        config.copyUninitializedValuesFromSecondaryConfig(loadDefaultConfigurationXml(context));
+        return config;
+    }
+
+    /**
+     * Creates an instance using global values since no display device config xml exists.
+     * Uses values from config or PowerManager.
+     *
+     * @param context
+     * @param useConfigXml
+     * @return A configuration instance.
+     */
+    public static DisplayDeviceConfig create(Context context, boolean useConfigXml) {
+        final DisplayDeviceConfig config;
+        if (useConfigXml) {
+            config = getConfigFromGlobalXml(context);
+        } else {
+            config = getConfigFromPmValues(context);
+        }
+        return config;
+    }
+
+    private static DisplayDeviceConfig createWithoutDefaultValues(Context context,
+            long physicalDisplayId, boolean isDefaultDisplay) {
         DisplayDeviceConfig config;
 
         config = loadConfigFromDirectory(context, Environment.getProductDirectory(),
@@ -161,22 +194,53 @@
         return create(context, isDefaultDisplay);
     }
 
-    /**
-     * Creates an instance using global values since no display device config xml exists.
-     * Uses values from config or PowerManager.
-     *
-     * @param context
-     * @param useConfigXml
-     * @return A configuration instance.
-     */
-    public static DisplayDeviceConfig create(Context context, boolean useConfigXml) {
-        DisplayDeviceConfig config;
-        if (useConfigXml) {
-            config = getConfigFromGlobalXml(context);
-        } else {
-            config = getConfigFromPmValues(context);
+    private static DisplayConfiguration loadDefaultConfigurationXml(Context context) {
+        List<File> defaultXmlLocations = new ArrayList<>();
+        defaultXmlLocations.add(Environment.buildPath(Environment.getProductDirectory(),
+                ETC_DIR, DISPLAY_CONFIG_DIR, DEFAULT_CONFIG_FILE));
+        defaultXmlLocations.add(Environment.buildPath(Environment.getVendorDirectory(),
+                ETC_DIR, DISPLAY_CONFIG_DIR, DEFAULT_CONFIG_FILE));
+
+        // Read config_defaultUiModeType directly because UiModeManager hasn't started yet.
+        final int uiModeType = context.getResources()
+                .getInteger(com.android.internal.R.integer.config_defaultUiModeType);
+        final String uiModeTypeStr = Configuration.getUiModeTypeString(uiModeType);
+        if (uiModeTypeStr != null) {
+            defaultXmlLocations.add(Environment.buildPath(Environment.getRootDirectory(),
+                    ETC_DIR, DISPLAY_CONFIG_DIR,
+                    String.format(DEFAULT_CONFIG_FILE_WITH_UIMODE_FORMAT, uiModeTypeStr)));
         }
-        return config;
+        defaultXmlLocations.add(Environment.buildPath(Environment.getRootDirectory(),
+                ETC_DIR, DISPLAY_CONFIG_DIR, DEFAULT_CONFIG_FILE));
+
+        final File configFile = getFirstExistingFile(defaultXmlLocations);
+        if (configFile == null) {
+            // Display configuration files aren't required to exist.
+            return null;
+        }
+
+        DisplayConfiguration defaultConfig = null;
+
+        try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
+            defaultConfig = XmlParser.read(in);
+            if (defaultConfig == null) {
+                Slog.i(TAG, "Default DisplayDeviceConfig file is null");
+            }
+        } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
+            Slog.e(TAG, "Encountered an error while reading/parsing display config file: "
+                    + configFile, e);
+        }
+
+        return defaultConfig;
+    }
+
+    private static File getFirstExistingFile(Collection<File> files) {
+        for (File file : files) {
+            if (file.exists() && file.isFile()) {
+                return file;
+            }
+        }
+        return null;
     }
 
     private static DisplayDeviceConfig loadConfigFromDirectory(Context context,
@@ -316,9 +380,13 @@
         return mRefreshRateLimitations;
     }
 
+    public DensityMap getDensityMap() {
+        return mDensityMap;
+    }
+
     @Override
     public String toString() {
-        String str = "DisplayDeviceConfig{"
+        return "DisplayDeviceConfig{"
                 + "mLoadedFrom=" + mLoadedFrom
                 + ", mBacklight=" + Arrays.toString(mBacklight)
                 + ", mNits=" + Arrays.toString(mNits)
@@ -340,8 +408,8 @@
                 + ", mAmbientLightSensor=" + mAmbientLightSensor
                 + ", mProximitySensor=" + mProximitySensor
                 + ", mRefreshRateLimitations= " + Arrays.toString(mRefreshRateLimitations.toArray())
+                + ", mDensityMap= " + mDensityMap
                 + "}";
-        return str;
     }
 
     private static DisplayDeviceConfig getConfigFromSuffix(Context context, File baseDirectory,
@@ -384,6 +452,7 @@
         try (InputStream in = new BufferedInputStream(new FileInputStream(configFile))) {
             final DisplayConfiguration config = XmlParser.read(in);
             if (config != null) {
+                loadDensityMap(config);
                 loadBrightnessDefaultFromDdcXml(config);
                 loadBrightnessConstraintsFromConfigXml();
                 loadBrightnessMap(config);
@@ -429,6 +498,35 @@
         setProxSensorUnspecified();
     }
 
+    private void copyUninitializedValuesFromSecondaryConfig(DisplayConfiguration defaultConfig) {
+        if (defaultConfig == null) {
+            return;
+        }
+
+        if (mDensityMap == null) {
+            loadDensityMap(defaultConfig);
+        }
+    }
+
+    private void loadDensityMap(DisplayConfiguration config) {
+        if (config.getDensityMap() == null) {
+            return;
+        }
+
+        final List<Density> entriesFromXml = config.getDensityMap().getDensity();
+
+        final DensityMap.Entry[] entries =
+                new DensityMap.Entry[entriesFromXml.size()];
+        for (int i = 0; i < entriesFromXml.size(); i++) {
+            final Density density = entriesFromXml.get(i);
+            entries[i] = new DensityMap.Entry(
+                    density.getWidth().intValue(),
+                    density.getHeight().intValue(),
+                    density.getDensity().intValue());
+        }
+        mDensityMap = DensityMap.createByOwning(entries);
+    }
+
     private void loadBrightnessDefaultFromDdcXml(DisplayConfiguration config) {
         // Default brightness values are stored in the displayDeviceConfig file,
         // Or we fallback standard values if not.
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 79b773e..a36a1a91 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -110,6 +110,7 @@
 import android.view.DisplayInfo;
 import android.view.Surface;
 import android.view.SurfaceControl;
+import android.window.DisplayWindowPolicyController;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -239,6 +240,10 @@
     public final SparseArray<CallbackRecord> mCallbacks =
             new SparseArray<CallbackRecord>();
 
+    /** All {@link DisplayWindowPolicyController}s indexed by {@link DisplayInfo#displayId}. */
+    final SparseArray<DisplayWindowPolicyController> mDisplayWindowPolicyController =
+            new SparseArray<>();
+
     // List of all currently registered display adapters.
     private final ArrayList<DisplayAdapter> mDisplayAdapters = new ArrayList<DisplayAdapter>();
 
@@ -524,6 +529,7 @@
             }
         } else if (phase == PHASE_BOOT_COMPLETED) {
             mDisplayModeDirector.onBootCompleted();
+            mLogicalDisplayMapper.onBootCompleted();
         }
     }
 
@@ -1114,46 +1120,211 @@
         }
     }
 
-    private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
-            IMediaProjection projection, int callingUid, String packageName, Surface surface,
-            int flags, VirtualDisplayConfig virtualDisplayConfig) {
-        synchronized (mSyncRoot) {
-            if (mVirtualDisplayAdapter == null) {
-                Slog.w(TAG, "Rejecting request to create private virtual display "
-                        + "because the virtual display adapter is not available.");
-                return -1;
+    private boolean validatePackageName(int uid, String packageName) {
+        if (packageName != null) {
+            String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
+            if (packageNames != null) {
+                for (String n : packageNames) {
+                    if (n.equals(packageName)) {
+                        return true;
+                    }
+                }
             }
-
-            DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
-                    callback, projection, callingUid, packageName, surface, flags,
-                    virtualDisplayConfig);
-            if (device == null) {
-                return -1;
-            }
-
-            // DisplayDevice events are handled manually for Virtual Displays.
-            // TODO: multi-display Fix this so that generic add/remove events are not handled in a
-            // different code path for virtual displays.  Currently this happens so that we can
-            // return a valid display ID synchronously upon successful Virtual Display creation.
-            // This code can run on any binder thread, while onDisplayDeviceAdded() callbacks are
-            // called on the DisplayThread (which we don't want to wait for?).
-            // One option would be to actually wait here on the binder thread
-            // to be notified when the virtual display is created (or failed).
-            mDisplayDeviceRepo.onDisplayDeviceEvent(device,
-                    DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
-
-            final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
-            if (display != null) {
-                return display.getDisplayIdLocked();
-            }
-
-            // Something weird happened and the logical display was not created.
-            Slog.w(TAG, "Rejecting request to create virtual display "
-                    + "because the logical display was not created.");
-            mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
-            mDisplayDeviceRepo.onDisplayDeviceEvent(device,
-                    DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
         }
+        return false;
+    }
+
+    private boolean canProjectVideo(IMediaProjection projection) {
+        if (projection != null) {
+            try {
+                if (projection.canProjectVideo()) {
+                    return true;
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Unable to query projection service for permissions", e);
+            }
+        }
+        if (checkCallingPermission(CAPTURE_VIDEO_OUTPUT, "canProjectVideo()")) {
+            return true;
+        }
+        return canProjectSecureVideo(projection);
+    }
+
+    private boolean canProjectSecureVideo(IMediaProjection projection) {
+        if (projection != null) {
+            try {
+                if (projection.canProjectSecureVideo()) {
+                    return true;
+                }
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Unable to query projection service for permissions", e);
+            }
+        }
+        return checkCallingPermission(CAPTURE_SECURE_VIDEO_OUTPUT, "canProjectSecureVideo()");
+    }
+
+    private boolean checkCallingPermission(String permission, String func) {
+        if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
+            return true;
+        }
+        final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
+                + ", uid=" + Binder.getCallingUid() + " requires " + permission;
+        Slog.w(TAG, msg);
+        return false;
+    }
+
+    private int createVirtualDisplayInternal(VirtualDisplayConfig virtualDisplayConfig,
+            IVirtualDisplayCallback callback, IMediaProjection projection, String packageName,
+            DisplayWindowPolicyController controller) {
+        final int callingUid = Binder.getCallingUid();
+        if (!validatePackageName(callingUid, packageName)) {
+            throw new SecurityException("packageName must match the calling uid");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("appToken must not be null");
+        }
+        if (virtualDisplayConfig == null) {
+            throw new IllegalArgumentException("virtualDisplayConfig must not be null");
+        }
+        final Surface surface = virtualDisplayConfig.getSurface();
+        int flags = virtualDisplayConfig.getFlags();
+
+        if (surface != null && surface.isSingleBuffered()) {
+            throw new IllegalArgumentException("Surface can't be single-buffered");
+        }
+
+        if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
+            flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
+
+            // Public displays can't be allowed to show content when locked.
+            if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
+                throw new IllegalArgumentException(
+                        "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE");
+            }
+        }
+        if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
+            flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
+        }
+        if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
+            flags &= ~VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP;
+        }
+
+        if (projection != null) {
+            try {
+                if (!getProjectionService().isValidMediaProjection(projection)) {
+                    throw new SecurityException("Invalid media projection");
+                }
+                flags = projection.applyVirtualDisplayFlags(flags);
+            } catch (RemoteException e) {
+                throw new SecurityException("unable to validate media projection or flags");
+            }
+        }
+
+        if (callingUid != Process.SYSTEM_UID
+                && (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
+            if (!canProjectVideo(projection)) {
+                throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
+                        + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
+                        + "MediaProjection token in order to create a screen sharing virtual "
+                        + "display.");
+            }
+        }
+        if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
+            if (!canProjectSecureVideo(projection)) {
+                throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
+                        + "or an appropriate MediaProjection token to create a "
+                        + "secure virtual display.");
+            }
+        }
+
+        if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) {
+            if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
+                EventLog.writeEvent(0x534e4554, "162627132", callingUid,
+                        "Attempt to create a trusted display without holding permission!");
+                throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
+                        + "create a trusted virtual display.");
+            }
+        }
+
+        if (callingUid != Process.SYSTEM_UID
+                && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) {
+            if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
+                throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
+                        + "create a virtual display which is not in the default DisplayGroup.");
+            }
+        }
+
+        if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) {
+            flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
+        }
+
+        // Sometimes users can have sensitive information in system decoration windows. An app
+        // could create a virtual display with system decorations support and read the user info
+        // from the surface.
+        // We should only allow adding flag VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+        // to trusted virtual displays.
+        final int trustedDisplayWithSysDecorFlag =
+                (VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+                        | VIRTUAL_DISPLAY_FLAG_TRUSTED);
+        if ((flags & trustedDisplayWithSysDecorFlag)
+                == VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
+                && !checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "createVirtualDisplay()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mSyncRoot) {
+                return createVirtualDisplayLocked(callback, projection, callingUid, packageName,
+                        surface, flags, virtualDisplayConfig, controller);
+            }
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    private int createVirtualDisplayLocked(IVirtualDisplayCallback callback,
+            IMediaProjection projection, int callingUid, String packageName, Surface surface,
+            int flags, VirtualDisplayConfig virtualDisplayConfig,
+            DisplayWindowPolicyController controller) {
+        if (mVirtualDisplayAdapter == null) {
+            Slog.w(TAG, "Rejecting request to create private virtual display "
+                    + "because the virtual display adapter is not available.");
+            return -1;
+        }
+
+        DisplayDevice device = mVirtualDisplayAdapter.createVirtualDisplayLocked(
+                callback, projection, callingUid, packageName, surface, flags,
+                virtualDisplayConfig);
+        if (device == null) {
+            return -1;
+        }
+
+        // DisplayDevice events are handled manually for Virtual Displays.
+        // TODO: multi-display Fix this so that generic add/remove events are not handled in a
+        // different code path for virtual displays.  Currently this happens so that we can
+        // return a valid display ID synchronously upon successful Virtual Display creation.
+        // This code can run on any binder thread, while onDisplayDeviceAdded() callbacks are
+        // called on the DisplayThread (which we don't want to wait for?).
+        // One option would be to actually wait here on the binder thread
+        // to be notified when the virtual display is created (or failed).
+        mDisplayDeviceRepo.onDisplayDeviceEvent(device,
+                DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
+
+        final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
+        if (display != null) {
+            if (controller != null) {
+                mDisplayWindowPolicyController.put(display.getDisplayIdLocked(), controller);
+            }
+            return display.getDisplayIdLocked();
+        }
+
+        // Something weird happened and the logical display was not created.
+        Slog.w(TAG, "Rejecting request to create virtual display "
+                + "because the logical display was not created.");
+        mVirtualDisplayAdapter.releaseVirtualDisplayLocked(callback.asBinder());
+        mDisplayDeviceRepo.onDisplayDeviceEvent(device,
+                DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
         return -1;
     }
 
@@ -1187,6 +1358,10 @@
             DisplayDevice device =
                     mVirtualDisplayAdapter.releaseVirtualDisplayLocked(appToken);
             if (device != null) {
+                final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(device);
+                if (display != null) {
+                    mDisplayWindowPolicyController.delete(display.getDisplayIdLocked());
+                }
                 // TODO: multi-display - handle virtual displays the same as other display adapters.
                 mDisplayDeviceRepo.onDisplayDeviceEvent(device,
                         DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
@@ -2138,6 +2313,15 @@
             }
             pw.println();
             mPersistentDataStore.dump(pw);
+
+            final int displayWindowPolicyControllerCount = mDisplayWindowPolicyController.size();
+            pw.println();
+            pw.println("Display Window Policy Controllers: size="
+                    + displayWindowPolicyControllerCount);
+            for (int i = 0; i < displayWindowPolicyControllerCount; i++) {
+                pw.print("Display " + mDisplayWindowPolicyController.keyAt(i) + ":");
+                mDisplayWindowPolicyController.valueAt(i).dump("  ", pw);
+            }
         }
         pw.println();
         mDisplayModeDirector.dump(pw);
@@ -2703,109 +2887,8 @@
         @Override // Binder call
         public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
                 IVirtualDisplayCallback callback, IMediaProjection projection, String packageName) {
-            final int callingUid = Binder.getCallingUid();
-            if (!validatePackageName(callingUid, packageName)) {
-                throw new SecurityException("packageName must match the calling uid");
-            }
-            if (callback == null) {
-                throw new IllegalArgumentException("appToken must not be null");
-            }
-            if (virtualDisplayConfig == null) {
-                throw new IllegalArgumentException("virtualDisplayConfig must not be null");
-            }
-            final Surface surface = virtualDisplayConfig.getSurface();
-            int flags = virtualDisplayConfig.getFlags();
-
-            if (surface != null && surface.isSingleBuffered()) {
-                throw new IllegalArgumentException("Surface can't be single-buffered");
-            }
-
-            if ((flags & VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
-                flags |= VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
-
-                // Public displays can't be allowed to show content when locked.
-                if ((flags & VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
-                    throw new IllegalArgumentException(
-                            "Public display must not be marked as SHOW_WHEN_LOCKED_INSECURE");
-                }
-            }
-            if ((flags & VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY) != 0) {
-                flags &= ~VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
-            }
-            if ((flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
-                flags &= ~VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP;
-            }
-
-            if (projection != null) {
-                try {
-                    if (!getProjectionService().isValidMediaProjection(projection)) {
-                        throw new SecurityException("Invalid media projection");
-                    }
-                    flags = projection.applyVirtualDisplayFlags(flags);
-                } catch (RemoteException e) {
-                    throw new SecurityException("unable to validate media projection or flags");
-                }
-            }
-
-            if (callingUid != Process.SYSTEM_UID &&
-                    (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
-                if (!canProjectVideo(projection)) {
-                    throw new SecurityException("Requires CAPTURE_VIDEO_OUTPUT or "
-                            + "CAPTURE_SECURE_VIDEO_OUTPUT permission, or an appropriate "
-                            + "MediaProjection token in order to create a screen sharing virtual "
-                            + "display.");
-                }
-            }
-            if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_SECURE) != 0) {
-                if (!canProjectSecureVideo(projection)) {
-                    throw new SecurityException("Requires CAPTURE_SECURE_VIDEO_OUTPUT "
-                            + "or an appropriate MediaProjection token to create a "
-                            + "secure virtual display.");
-                }
-            }
-
-            if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) {
-                if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
-                    EventLog.writeEvent(0x534e4554, "162627132", callingUid,
-                            "Attempt to create a trusted display without holding permission!");
-                    throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
-                            + "create a trusted virtual display.");
-                }
-            }
-
-            if (callingUid != Process.SYSTEM_UID
-                    && (flags & VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP) != 0) {
-                if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
-                    throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
-                            + "create a virtual display which is not in the default DisplayGroup.");
-                }
-            }
-
-            if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) {
-                flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
-            }
-
-            // Sometimes users can have sensitive information in system decoration windows. An app
-            // could create a virtual display with system decorations support and read the user info
-            // from the surface.
-            // We should only allow adding flag VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
-            // to trusted virtual displays.
-            final int trustedDisplayWithSysDecorFlag =
-                    (VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
-                            | VIRTUAL_DISPLAY_FLAG_TRUSTED);
-            if ((flags & trustedDisplayWithSysDecorFlag)
-                    == VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
-                    && !checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "createVirtualDisplay()")) {
-                    throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
-            }
-
-            final long token = Binder.clearCallingIdentity();
-            try {
-                return createVirtualDisplayInternal(callback, projection, callingUid, packageName,
-                        surface, flags, virtualDisplayConfig);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
+            return createVirtualDisplayInternal(virtualDisplayConfig, callback, projection,
+                    packageName, null /* controller */);
         }
 
         @Override // Binder call
@@ -3235,60 +3318,6 @@
                 Binder.restoreCallingIdentity(token);
             }
         }
-
-        private boolean validatePackageName(int uid, String packageName) {
-            if (packageName != null) {
-                String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
-                if (packageNames != null) {
-                    for (String n : packageNames) {
-                        if (n.equals(packageName)) {
-                            return true;
-                        }
-                    }
-                }
-            }
-            return false;
-        }
-
-        private boolean canProjectVideo(IMediaProjection projection) {
-            if (projection != null) {
-                try {
-                    if (projection.canProjectVideo()) {
-                        return true;
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to query projection service for permissions", e);
-                }
-            }
-            if (checkCallingPermission(CAPTURE_VIDEO_OUTPUT, "canProjectVideo()")) {
-                return true;
-            }
-            return canProjectSecureVideo(projection);
-        }
-
-        private boolean canProjectSecureVideo(IMediaProjection projection) {
-            if (projection != null) {
-                try {
-                    if (projection.canProjectSecureVideo()){
-                        return true;
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Unable to query projection service for permissions", e);
-                }
-            }
-            return checkCallingPermission(CAPTURE_SECURE_VIDEO_OUTPUT, "canProjectSecureVideo()");
-        }
-
-        private boolean checkCallingPermission(String permission, String func) {
-            if (mContext.checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
-                return true;
-            }
-            final String msg = "Permission Denial: " + func + " from pid=" + Binder.getCallingPid()
-                    + ", uid=" + Binder.getCallingUid() + " requires " + permission;
-            Slog.w(TAG, msg);
-            return false;
-        }
-
     }
 
     private static boolean isValidBrightness(float brightness) {
@@ -3618,6 +3647,26 @@
             }
             return device.getDisplaySurfaceDefaultSize();
         }
+
+        @Override
+        public void onEarlyInteractivityChange(boolean interactive) {
+            mLogicalDisplayMapper.onEarlyInteractivityChange(interactive);
+        }
+
+        @Override
+        public int createVirtualDisplay(VirtualDisplayConfig virtualDisplayConfig,
+                IVirtualDisplayCallback callback, IMediaProjection projection, String packageName,
+                DisplayWindowPolicyController controller) {
+            return createVirtualDisplayInternal(virtualDisplayConfig, callback, projection,
+                    packageName, controller);
+        }
+
+        @Override
+        public DisplayWindowPolicyController getDisplayWindowPolicyController(int displayId) {
+            synchronized (mSyncRoot) {
+                return mDisplayWindowPolicyController.get(displayId);
+            }
+        }
     }
 
     class DesiredDisplayModeSpecsObserver
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 2f3342f..7f78cac 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -54,6 +54,7 @@
 import android.util.TimeUtils;
 import android.view.Display;
 
+import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.display.BrightnessSynchronizer;
@@ -108,8 +109,6 @@
     // screen state returns.  Playing the animation can also be somewhat slow.
     private static final boolean USE_COLOR_FADE_ON_ANIMATION = false;
 
-    // The minimum reduction in brightness when dimmed.
-    private static final float SCREEN_DIM_MINIMUM_REDUCTION_FLOAT = 0.04f;
     private static final float SCREEN_ANIMATION_RATE_MINIMUM = 0.0f;
 
     private static final int COLOR_FADE_ON_ANIMATION_DURATION_MILLIS = 250;
@@ -200,6 +199,10 @@
     // The dim screen brightness.
     private final float mScreenBrightnessDimConfig;
 
+    // The minimum dim amount to use if the screen brightness is already below
+    // mScreenBrightnessDimConfig.
+    private final float mScreenBrightnessMinimumDimAmount;
+
     private final float mScreenBrightnessDefault;
 
     // The minimum allowed brightness while in VR.
@@ -384,8 +387,17 @@
     private Sensor mLightSensor;
 
     // The mapper between ambient lux, display backlight values, and display brightness.
+    // This mapper holds the current one that is being used. We will switch between the idle
+    // mapper and active mapper here.
     @Nullable
-    private BrightnessMappingStrategy mBrightnessMapper;
+    private BrightnessMappingStrategy mCurrentBrightnessMapper;
+
+    // Mapper used for active (normal) screen brightness mode
+    @Nullable
+    private BrightnessMappingStrategy mInteractiveModeBrightnessMapper;
+    // Mapper used for idle screen brightness mode
+    @Nullable
+    private BrightnessMappingStrategy mIdleModeBrightnessMapper;
 
     // The current brightness configuration.
     @Nullable
@@ -406,7 +418,7 @@
 
     // The temporary screen brightness. Typically set when a user is interacting with the
     // brightness slider but hasn't settled on a choice yet. Set to
-    // PowerManager.BRIGHNTESS_INVALID_FLOAT when there's no temporary brightness set.
+    // PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary brightness set.
     private float mTemporaryScreenBrightness;
 
     // The current screen brightness while in VR mode.
@@ -485,6 +497,9 @@
                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DOZE));
         mScreenBrightnessDimConfig = clampAbsoluteBrightness(
                 pm.getBrightnessConstraint(PowerManager.BRIGHTNESS_CONSTRAINT_TYPE_DIM));
+        mScreenBrightnessMinimumDimAmount = resources.getFloat(
+                com.android.internal.R.dimen.config_screenBrightnessMinimumDimAmountFloat);
+
 
         // NORMAL SCREEN SETTINGS
         mScreenBrightnessDefault = clampAbsoluteBrightness(
@@ -595,7 +610,7 @@
     }
 
     private void handleRbcChanged(boolean strengthChanged, boolean justActivated) {
-        if (mBrightnessMapper == null) {
+        if (mCurrentBrightnessMapper == null) {
             Log.w(TAG, "No brightness mapping available to recalculate splines");
             return;
         }
@@ -604,7 +619,8 @@
         for (int i = 0; i < mNitsRange.length; i++) {
             adjustedNits[i] = mCdsi.getReduceBrightColorsAdjustedBrightnessNits(mNitsRange[i]);
         }
-        mBrightnessMapper.recalculateSplines(mCdsi.isReduceBrightColorsActivated(), adjustedNits);
+        mCurrentBrightnessMapper.recalculateSplines(mCdsi.isReduceBrightColorsActivated(),
+                adjustedNits);
 
         mPendingRbcOnOrChanged = strengthChanged || justActivated;
 
@@ -862,9 +878,17 @@
             return;
         }
 
-        mBrightnessMapper = BrightnessMappingStrategy.create(resources, mDisplayDeviceConfig);
+        final boolean isIdleScreenBrightnessEnabled = resources.getBoolean(
+                R.bool.config_enableIdleScreenBrightnessMode);
+        mInteractiveModeBrightnessMapper = BrightnessMappingStrategy.create(resources,
+                mDisplayDeviceConfig);
+        if (isIdleScreenBrightnessEnabled) {
+            mIdleModeBrightnessMapper = BrightnessMappingStrategy.createForIdleMode(resources,
+                    mDisplayDeviceConfig);
+        }
+        mCurrentBrightnessMapper = mInteractiveModeBrightnessMapper;
 
-        if (mBrightnessMapper != null) {
+        if (mCurrentBrightnessMapper != null) {
             final float dozeScaleFactor = resources.getFraction(
                     com.android.internal.R.fraction.config_screenAutoBrightnessDozeScaleFactor,
                     1, 1);
@@ -915,12 +939,12 @@
                 mAutomaticBrightnessController.stop();
             }
             mAutomaticBrightnessController = new AutomaticBrightnessController(this,
-                    handler.getLooper(), mSensorManager, mLightSensor, mBrightnessMapper,
+                    handler.getLooper(), mSensorManager, mLightSensor, mCurrentBrightnessMapper,
                     lightSensorWarmUpTimeConfig, PowerManager.BRIGHTNESS_MIN,
                     PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate,
                     initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce,
                     autoBrightnessResetAmbientLuxAfterWarmUp, ambientBrightnessThresholds,
-                    screenBrightnessThresholds, mLogicalDisplay, mContext, mHbmController);
+                    screenBrightnessThresholds, mContext, mHbmController);
         } else {
             mUseSoftwareAutoBrightnessConfig = false;
         }
@@ -1284,7 +1308,7 @@
         if (mPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
             if (brightnessState > PowerManager.BRIGHTNESS_MIN) {
                 brightnessState = Math.max(
-                        Math.min(brightnessState - SCREEN_DIM_MINIMUM_REDUCTION_FLOAT,
+                        Math.min(brightnessState - mScreenBrightnessMinimumDimAmount,
                                 mScreenBrightnessDimConfig),
                         PowerManager.BRIGHTNESS_MIN);
                 mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
@@ -2138,8 +2162,8 @@
     }
 
     private float convertToNits(float brightness) {
-        if (mBrightnessMapper != null) {
-            return mBrightnessMapper.convertToNits(brightness);
+        if (mCurrentBrightnessMapper != null) {
+            return mCurrentBrightnessMapper.convertToNits(brightness);
         } else {
             return -1.0f;
         }
@@ -2291,6 +2315,11 @@
         pw.println("  mReportedToPolicy=" +
                 reportedToPolicyToString(mReportedScreenStateToPolicy));
 
+        if (mIdleModeBrightnessMapper != null) {
+            pw.println("  mIdleModeBrightnessMapper= ");
+            mIdleModeBrightnessMapper.dump(pw);
+        }
+
         if (mScreenBrightnessRampAnimator != null) {
             pw.println("  mScreenBrightnessRampAnimator.isAnimating()=" +
                     mScreenBrightnessRampAnimator.isAnimating());
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index b6d13e0..300f59e 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -426,6 +426,15 @@
                     : mDefaultModeId;
         }
 
+        private int getLogicalDensity() {
+            DensityMap densityMap = getDisplayDeviceConfig().getDensityMap();
+            if (densityMap == null) {
+                return (int) (mStaticDisplayInfo.density * 160 + 0.5);
+            }
+
+            return densityMap.getDensityForResolution(mInfo.width, mInfo.height);
+        }
+
         private void loadDisplayDeviceConfig() {
             // Load display device config
             final Context context = getOverlayContext();
@@ -591,7 +600,7 @@
                 final DisplayAddress.Physical physicalAddress =
                         DisplayAddress.fromPhysicalDisplayId(mPhysicalDisplayId);
                 mInfo.address = physicalAddress;
-                mInfo.densityDpi = (int) (mStaticDisplayInfo.density * 160 + 0.5f);
+                mInfo.densityDpi = getLogicalDensity();
                 mInfo.xDpi = mActiveSfDisplayMode.xDpi;
                 mInfo.yDpi = mActiveSfDisplayMode.yDpi;
                 mInfo.deviceProductInfo = mStaticDisplayInfo.deviceProductInfo;
@@ -1029,7 +1038,7 @@
             for (int i = 0; i < mSupportedModes.size(); i++) {
                 pw.println("  " + mSupportedModes.valueAt(i));
             }
-            pw.println("mSupportedColorModes=" + mSupportedColorModes.toString());
+            pw.println("mSupportedColorModes=" + mSupportedColorModes);
             pw.println("mDisplayDeviceConfig=" + mDisplayDeviceConfig);
         }
 
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 0fbc3e8..7719dfe 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -30,6 +30,7 @@
 import android.util.IndentingPrintWriter;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 import android.view.Display;
 import android.view.DisplayAddress;
@@ -71,7 +72,7 @@
     public static final int DISPLAY_GROUP_EVENT_CHANGED = 2;
     public static final int DISPLAY_GROUP_EVENT_REMOVED = 3;
 
-    private static final int TIMEOUT_STATE_TRANSITION_MILLIS = 300;
+    private static final int TIMEOUT_STATE_TRANSITION_MILLIS = 500;
 
     private static final int MSG_TRANSITION_TO_PENDING_DEVICE_STATE = 1;
 
@@ -100,9 +101,14 @@
     private final boolean mSupportsConcurrentInternalDisplays;
 
     /**
-     * Wake the device when transitioning into this device state.
+     * Wake the device when transitioning into these device state.
      */
-    private final int mDeviceStateOnWhichToWakeUp;
+    private final SparseBooleanArray mDeviceStatesOnWhichToWakeUp;
+
+    /**
+     * Sleep the device when transitioning into these device state.
+     */
+    private final SparseBooleanArray mDeviceStatesOnWhichToSleep;
 
     /**
      * Map of all logical displays indexed by logical display id.
@@ -153,20 +159,25 @@
     private Layout mCurrentLayout = null;
     private int mDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
     private int mPendingDeviceState = DeviceStateManager.INVALID_DEVICE_STATE;
+    private boolean mBootCompleted = false;
+    private boolean mInteractive;
 
     LogicalDisplayMapper(@NonNull Context context, @NonNull DisplayDeviceRepository repo,
             @NonNull Listener listener, @NonNull DisplayManagerService.SyncRoot syncRoot,
             @NonNull Handler handler) {
         mSyncRoot = syncRoot;
         mPowerManager = context.getSystemService(PowerManager.class);
+        mInteractive = mPowerManager.isInteractive();
         mHandler = new LogicalDisplayMapperHandler(handler.getLooper());
         mDisplayDeviceRepo = repo;
         mListener = listener;
         mSingleDisplayDemoMode = SystemProperties.getBoolean("persist.demo.singledisplay", false);
         mSupportsConcurrentInternalDisplays = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_supportsConcurrentInternalDisplays);
-        mDeviceStateOnWhichToWakeUp = context.getResources().getInteger(
-                com.android.internal.R.integer.config_deviceStateOnWhichToWakeUp);
+        mDeviceStatesOnWhichToWakeUp = toSparseBooleanArray(context.getResources().getIntArray(
+                com.android.internal.R.array.config_deviceStatesOnWhichToWakeUp));
+        mDeviceStatesOnWhichToSleep = toSparseBooleanArray(context.getResources().getIntArray(
+                com.android.internal.R.array.config_deviceStatesOnWhichToSleep));
         mDisplayDeviceRepo.addListener(this);
         mDeviceStateToLayoutMap = new DeviceStateToLayoutMap();
     }
@@ -329,7 +340,9 @@
 
         ipw.println("mSingleDisplayDemoMode=" + mSingleDisplayDemoMode);
         ipw.println("mCurrentLayout=" + mCurrentLayout);
-        ipw.println("mDeviceStateOnWhichToWakeUp=" + mDeviceStateOnWhichToWakeUp);
+        ipw.println("mDeviceStatesOnWhichToWakeUp=" + mDeviceStatesOnWhichToWakeUp);
+        ipw.println("mDeviceStatesOnWhichToSleep=" + mDeviceStatesOnWhichToSleep);
+        ipw.println("mInteractive=" + mInteractive);
 
         final int logicalDisplayCount = mLogicalDisplays.size();
         ipw.println();
@@ -347,9 +360,8 @@
     }
 
     void setDeviceStateLocked(int state) {
-        final boolean isInteractive  = mPowerManager.isInteractive();
         Slog.i(TAG, "Requesting Transition to state: " + state + ", from state=" + mDeviceState
-                + ", interactive=" + isInteractive);
+                + ", interactive=" + mInteractive);
         // As part of a state transition, we may need to turn off some displays temporarily so that
         // the transition is smooth. Plus, on some devices, only one internal displays can be
         // on at a time. We use DISPLAY_PHASE_LAYOUT_TRANSITION to mark a display that needs to be
@@ -358,13 +370,17 @@
             resetLayoutLocked(mDeviceState, state, LogicalDisplay.DISPLAY_PHASE_LAYOUT_TRANSITION);
         }
         mPendingDeviceState = state;
-        final boolean wakeDevice = mPendingDeviceState == mDeviceStateOnWhichToWakeUp
-                && !isInteractive;
+        final boolean wakeDevice = mDeviceStatesOnWhichToWakeUp.get(mPendingDeviceState)
+                && !mDeviceStatesOnWhichToWakeUp.get(mDeviceState)
+                && !mInteractive && mBootCompleted;
+        final boolean sleepDevice = mDeviceStatesOnWhichToSleep.get(mPendingDeviceState)
+                && !mDeviceStatesOnWhichToSleep.get(mDeviceState)
+                && mInteractive && mBootCompleted;
 
-        // If all displays are off already, we can just transition here, unless the device is asleep
-        // and we plan on waking it up. In that case, fall through to the call to wakeUp, and defer
-        // the final transition until later once the device is awake.
-        if (areAllTransitioningDisplaysOffLocked() && !wakeDevice) {
+        // If all displays are off already, we can just transition here, unless we are trying to
+        // wake or sleep the device as part of this transition. In that case defer the final
+        // transition until later once the device is awake/asleep.
+        if (areAllTransitioningDisplaysOffLocked() && !wakeDevice && !sleepDevice) {
             transitionToPendingStateLocked();
             return;
         }
@@ -376,17 +392,39 @@
         // start turning OFF in preparation for the new layout.
         updateLogicalDisplaysLocked();
 
-        if (wakeDevice) {
-            // We already told the displays to turn off, now we need to wake the device as
-            // we transition to this new state. We do it here so that the waking happens between the
-            // transition from one layout to another.
-            mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_UNFOLD_DEVICE,
-                    "server.display:unfold");
+        if (wakeDevice || sleepDevice) {
+            if (wakeDevice) {
+                // We already told the displays to turn off, now we need to wake the device as
+                // we transition to this new state. We do it here so that the waking happens
+                // between the transition from one layout to another.
+                mPowerManager.wakeUp(SystemClock.uptimeMillis(),
+                        PowerManager.WAKE_REASON_UNFOLD_DEVICE, "server.display:unfold");
+            } else if (sleepDevice) {
+                // Send the device to sleep when required.
+                mPowerManager.goToSleep(SystemClock.uptimeMillis(),
+                        PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD, 0);
+            }
         }
+
         mHandler.sendEmptyMessageDelayed(MSG_TRANSITION_TO_PENDING_DEVICE_STATE,
                 TIMEOUT_STATE_TRANSITION_MILLIS);
     }
 
+    void onBootCompleted() {
+        synchronized (mSyncRoot) {
+            mBootCompleted = true;
+        }
+    }
+
+    void onEarlyInteractivityChange(boolean interactive) {
+        synchronized (mSyncRoot) {
+            if (mInteractive != interactive) {
+                mInteractive = interactive;
+                finishStateTransitionLocked(false /*force*/);
+            }
+        }
+    }
+
     private boolean areAllTransitioningDisplaysOffLocked() {
         final int count = mLogicalDisplays.size();
         for (int i = 0; i < count; i++) {
@@ -419,13 +457,24 @@
             return;
         }
 
+        final boolean waitingToWakeDevice = mDeviceStatesOnWhichToWakeUp.get(mPendingDeviceState)
+                && !mDeviceStatesOnWhichToWakeUp.get(mDeviceState)
+                && !mInteractive && mBootCompleted;
+        final boolean waitingToSleepDevice = mDeviceStatesOnWhichToSleep.get(mPendingDeviceState)
+                && !mDeviceStatesOnWhichToSleep.get(mDeviceState)
+                && mInteractive && mBootCompleted;
+
         final boolean displaysOff = areAllTransitioningDisplaysOffLocked();
-        if (displaysOff || force) {
+        final boolean isReadyToTransition = displaysOff && !waitingToWakeDevice
+                && !waitingToSleepDevice;
+
+        if (isReadyToTransition || force) {
             transitionToPendingStateLocked();
             mHandler.removeMessages(MSG_TRANSITION_TO_PENDING_DEVICE_STATE);
         } else if (DEBUG) {
             Slog.d(TAG, "Not yet ready to transition to state=" + mPendingDeviceState
-                    + " with displays-off=" + displaysOff + " and force=" + force);
+                    + " with displays-off=" + displaysOff + ", force=" + force
+                    + ", mInteractive=" + mInteractive + ", isReady=" + isReadyToTransition);
         }
     }
 
@@ -821,6 +870,14 @@
         return displayId;
     }
 
+    private SparseBooleanArray toSparseBooleanArray(int[] input) {
+        final SparseBooleanArray retval = new SparseBooleanArray(2);
+        for (int i = 0; input != null && i < input.length; i++) {
+            retval.put(input[i], true);
+        }
+        return retval;
+    }
+
     private String displayEventToString(int msg) {
         switch(msg) {
             case LOGICAL_DISPLAY_EVENT_ADDED:
@@ -861,5 +918,4 @@
             }
         }
     }
-
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 1fa6241..7e71589 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -265,13 +265,20 @@
         // to request Short Audio Descriptor. Since ARC and SAM are independent,
         // we can turn on ARC anyways when audio system device just boots up.
         initArcOnFromAvr();
-        int systemAudioControlOnPowerOnProp =
-                SystemProperties.getInt(
-                        PROPERTY_SYSTEM_AUDIO_CONTROL_ON_POWER_ON,
-                        ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON);
-        boolean lastSystemAudioControlStatus =
-                SystemProperties.getBoolean(Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL, true);
-        systemAudioControlOnPowerOn(systemAudioControlOnPowerOnProp, lastSystemAudioControlStatus);
+
+        // This prevents turning on of System Audio Mode during a quiescent boot. If the quiescent
+        // boot is exited just after this check, this code will be executed only at the next
+        // wake-up.
+        if (!mService.isScreenOff()) {
+            int systemAudioControlOnPowerOnProp =
+                    SystemProperties.getInt(
+                            PROPERTY_SYSTEM_AUDIO_CONTROL_ON_POWER_ON,
+                            ALWAYS_SYSTEM_AUDIO_CONTROL_ON_POWER_ON);
+            boolean lastSystemAudioControlStatus =
+                    SystemProperties.getBoolean(Constants.PROPERTY_LAST_SYSTEM_AUDIO_CONTROL, true);
+            systemAudioControlOnPowerOn(
+                    systemAudioControlOnPowerOnProp, lastSystemAudioControlStatus);
+        }
         mService.getHdmiCecNetwork().clearDeviceList();
         launchDeviceDiscovery();
         startQueuedActions();
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index d6ac25a..b23395f 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -21,6 +21,7 @@
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.hardware.hdmi.IHdmiControlCallback;
 import android.hardware.tv.cec.V1_0.SendMessageResult;
+import android.os.Handler;
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
 import android.os.SystemProperties;
@@ -47,6 +48,10 @@
     private static final boolean SET_MENU_LANGUAGE =
             HdmiProperties.set_menu_language_enabled().orElse(false);
 
+    // How long to wait after hotplug out before possibly going to Standby.
+    @VisibleForTesting
+    static final long STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS = 30_000;
+
     // Used to keep the device awake while it is the active source. For devices that
     // cannot wake up via CEC commands, this address the inconvenience of having to
     // turn them on. True by default, and can be disabled (i.e. device can go to sleep
@@ -55,6 +60,9 @@
     // Lazily initialized - should call getWakeLock() to get the instance.
     private ActiveWakeLock mWakeLock;
 
+    // Handler for queueing a delayed Standby runnable after hotplug out.
+    private Handler mDelayedStandbyHandler;
+
     // Determines what action should be taken upon receiving Routing Control messages.
     @VisibleForTesting
     protected HdmiProperties.playback_device_action_on_routing_control_values
@@ -64,6 +72,8 @@
 
     HdmiCecLocalDevicePlayback(HdmiControlService service) {
         super(service, HdmiDeviceInfo.DEVICE_PLAYBACK);
+
+        mDelayedStandbyHandler = new Handler(service.getServiceLooper());
     }
 
     @Override
@@ -195,9 +205,33 @@
     void onHotplug(int portId, boolean connected) {
         assertRunOnServiceThread();
         mCecMessageCache.flushAll();
-        // We'll not invalidate the active source on the hotplug event to pass CETC 11.2.2-2 ~ 3.
-        if (!connected) {
+
+        if (connected) {
+            mDelayedStandbyHandler.removeCallbacksAndMessages(null);
+        } else {
+            // We'll not invalidate the active source on the hotplug event to pass CETC 11.2.2-2 ~ 3
             getWakeLock().release();
+
+            mDelayedStandbyHandler.removeCallbacksAndMessages(null);
+            mDelayedStandbyHandler.postDelayed(new DelayedStandbyRunnable(),
+                    STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS);
+        }
+    }
+
+    /**
+     * Runnable for going to Standby if the device has been inactive for a certain amount of time.
+     * Posts a new instance of itself as a delayed message if the device was active.
+     */
+    private class DelayedStandbyRunnable implements Runnable {
+        @Override
+        public void run() {
+            if (mService.getPowerManagerInternal().wasDeviceIdleFor(
+                    STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS)) {
+                mService.standby();
+            } else {
+                mDelayedStandbyHandler.postDelayed(new DelayedStandbyRunnable(),
+                        STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 69f7af2..6dd9aa0 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -37,6 +37,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.database.ContentObserver;
+import android.hardware.display.DisplayManager;
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiDeviceInfo;
 import android.hardware.hdmi.HdmiHotplugEvent;
@@ -81,6 +82,7 @@
 import android.util.ArrayMap;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.view.Display;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
@@ -408,8 +410,14 @@
     private PowerManagerWrapper mPowerManager;
 
     @Nullable
+    private PowerManagerInternalWrapper mPowerManagerInternal;
+
+    @Nullable
     private Looper mIoLooper;
 
+    @Nullable
+    private DisplayManager mDisplayManager;
+
     @HdmiControlManager.HdmiCecVersion
     private int mCecVersion;
 
@@ -676,6 +684,11 @@
                 }, mServiceThreadExecutor);
     }
 
+    /** Returns true if the device screen is off */
+    boolean isScreenOff() {
+        return mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState() == Display.STATE_OFF;
+    }
+
     private void bootCompleted() {
         // on boot, if device is interactive, set HDMI CEC state as powered on as well
         if (mPowerManager.isInteractive() && isPowerStandbyOrTransient()) {
@@ -731,9 +744,11 @@
     @Override
     public void onBootPhase(int phase) {
         if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+            mDisplayManager = getContext().getSystemService(DisplayManager.class);
             mTvInputManager = (TvInputManager) getContext().getSystemService(
                     Context.TV_INPUT_SERVICE);
             mPowerManager = new PowerManagerWrapper(getContext());
+            mPowerManagerInternal = new PowerManagerInternalWrapper();
         } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
             runOnServiceThread(this::bootCompleted);
         }
@@ -758,10 +773,19 @@
         mPowerManager = powerManager;
     }
 
+    @VisibleForTesting
+    void setPowerManagerInternal(PowerManagerInternalWrapper powerManagerInternal) {
+        mPowerManagerInternal = powerManagerInternal;
+    }
+
     PowerManagerWrapper getPowerManager() {
         return mPowerManager;
     }
 
+    PowerManagerInternalWrapper getPowerManagerInternal() {
+        return mPowerManagerInternal;
+    }
+
     /**
      * Called when the initialization of local devices is complete.
      */
@@ -3239,18 +3263,19 @@
         assertRunOnServiceThread();
         Slog.v(TAG, "onPendingActionsCleared");
 
-        if (!mPowerStatusController.isPowerStatusTransientToStandby()) {
-            return;
+        if (mPowerStatusController.isPowerStatusTransientToStandby()) {
+            mPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_STANDBY);
+            for (HdmiCecLocalDevice device : mHdmiCecNetwork.getLocalDeviceList()) {
+                device.onStandby(mStandbyMessageReceived, standbyAction);
+            }
+            if (!isAudioSystemDevice()) {
+                mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, false);
+                mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, DISABLED);
+            }
         }
-        mPowerStatusController.setPowerStatus(HdmiControlManager.POWER_STATUS_STANDBY);
-        for (HdmiCecLocalDevice device : mHdmiCecNetwork.getLocalDeviceList()) {
-            device.onStandby(mStandbyMessageReceived, standbyAction);
-        }
+
+        // Always reset this flag to set up for the next standby
         mStandbyMessageReceived = false;
-        if (!isAudioSystemDevice()) {
-            mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, false);
-            mMhlController.setOption(OPTION_MHL_SERVICE_CONTROL, DISABLED);
-        }
     }
 
     private void addVendorCommandListener(IHdmiVendorCommandListener listener, int deviceType) {
diff --git a/services/core/java/com/android/server/hdmi/PowerManagerInternalWrapper.java b/services/core/java/com/android/server/hdmi/PowerManagerInternalWrapper.java
new file mode 100644
index 0000000..59671a8
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/PowerManagerInternalWrapper.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 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.hdmi;
+
+import android.os.PowerManagerInternal;
+
+import com.android.server.LocalServices;
+
+/**
+ * Abstraction around {@link PowerManagerInternal} to allow faking it in tests.
+ */
+public class PowerManagerInternalWrapper {
+    private static final String TAG = "PowerManagerInternalWrapper";
+
+    private PowerManagerInternal mPowerManagerInternal;
+
+    public PowerManagerInternalWrapper() {
+        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
+    }
+
+    /**
+     * Wraps {@link PowerManagerInternal#wasDeviceIdleFor(long)}
+     */
+    public boolean wasDeviceIdleFor(long ms) {
+        return mPowerManagerInternal.wasDeviceIdleFor(ms);
+    }
+}
diff --git a/services/core/java/com/android/server/health/HealthRegCallbackAidl.java b/services/core/java/com/android/server/health/HealthRegCallbackAidl.java
new file mode 100644
index 0000000..629011a
--- /dev/null
+++ b/services/core/java/com/android/server/health/HealthRegCallbackAidl.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2021 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.health;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.health.HealthInfo;
+import android.hardware.health.IHealth;
+import android.hardware.health.IHealthInfoCallback;
+import android.os.RemoteException;
+import android.os.Trace;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * On service registration, {@link #onRegistration} is called, which registers {@code this}, an
+ * {@link IHealthInfoCallback}, to the health service.
+ *
+ * <p>When the health service has updates to health info via {@link IHealthInfoCallback}, {@link
+ * HealthInfoCallback#update} is called.
+ *
+ * <p>AIDL variant of {@link HealthHalCallbackHidl}.
+ *
+ * @hide
+ */
+// It is made public so Mockito can access this class. It should have been package private if not
+// for testing.
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public class HealthRegCallbackAidl {
+    private static final String TAG = "HealthRegCallbackAidl";
+    private final HealthInfoCallback mServiceInfoCallback;
+    private final IHealthInfoCallback mHalInfoCallback = new HalInfoCallback();
+
+    HealthRegCallbackAidl(@Nullable HealthInfoCallback healthInfoCallback) {
+        mServiceInfoCallback = healthInfoCallback;
+    }
+
+    /**
+     * Called when the service manager sees {@code newService} replacing {@code oldService}.
+     * This unregisters the health info callback from the old service (ignoring errors), then
+     * registers the health info callback to the new service.
+     *
+     * @param oldService the old IHealth service
+     * @param newService the new IHealth service
+     */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public void onRegistration(@Nullable IHealth oldService, @NonNull IHealth newService) {
+        if (mServiceInfoCallback == null) return;
+
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "HealthUnregisterCallbackAidl");
+        try {
+            unregisterCallback(oldService, mHalInfoCallback);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+        }
+
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "HealthRegisterCallbackAidl");
+        try {
+            registerCallback(newService, mHalInfoCallback);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+        }
+    }
+
+    private static void unregisterCallback(@Nullable IHealth oldService, IHealthInfoCallback cb) {
+        if (oldService == null) return;
+        try {
+            oldService.unregisterCallback(cb);
+        } catch (RemoteException e) {
+            // Ignore errors. The service might have died.
+            Slog.w(
+                    TAG,
+                    "health: cannot unregister previous callback (transaction error): "
+                            + e.getMessage());
+        }
+    }
+
+    private static void registerCallback(@NonNull IHealth newService, IHealthInfoCallback cb) {
+        try {
+            newService.registerCallback(cb);
+        } catch (RemoteException e) {
+            Slog.e(
+                    TAG,
+                    "health: cannot register callback, framework may cease to"
+                            + " receive updates on health / battery info!",
+                    e);
+            return;
+        }
+        // registerCallback does NOT guarantee that update is called immediately, so request a
+        // manual update here.
+        try {
+            newService.update();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "health: cannot update after registering health info callback", e);
+        }
+    }
+
+    private class HalInfoCallback extends IHealthInfoCallback.Stub {
+        @Override
+        public void healthInfoChanged(HealthInfo healthInfo) throws RemoteException {
+            mServiceInfoCallback.update(healthInfo);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/health/HealthServiceWrapper.java b/services/core/java/com/android/server/health/HealthServiceWrapper.java
index 9b97554..25d1a88 100644
--- a/services/core/java/com/android/server/health/HealthServiceWrapper.java
+++ b/services/core/java/com/android/server/health/HealthServiceWrapper.java
@@ -81,6 +81,8 @@
     public static HealthServiceWrapper create(@Nullable HealthInfoCallback healthInfoCallback)
             throws RemoteException, NoSuchElementException {
         return create(
+                healthInfoCallback == null ? null : new HealthRegCallbackAidl(healthInfoCallback),
+                new HealthServiceWrapperAidl.ServiceManagerStub() {},
                 healthInfoCallback == null ? null : new HealthHalCallbackHidl(healthInfoCallback),
                 new HealthServiceWrapperHidl.IServiceManagerSupplier() {},
                 new HealthServiceWrapperHidl.IHealthSupplier() {});
@@ -89,6 +91,9 @@
     /**
      * Create a new HealthServiceWrapper instance for testing.
      *
+     * @param aidlRegCallback callback for AIDL service registration, or {@code null} if the client
+     *     does not care about AIDL service registration notifications
+     * @param aidlServiceManager Stub for AIDL ServiceManager
      * @param hidlRegCallback callback for HIDL service registration, or {@code null} if the client
      *     does not care about HIDL service registration notifications
      * @param hidlServiceManagerSupplier supplier of HIDL service manager
@@ -97,10 +102,17 @@
      */
     @VisibleForTesting
     static @NonNull HealthServiceWrapper create(
+            @Nullable HealthRegCallbackAidl aidlRegCallback,
+            @NonNull HealthServiceWrapperAidl.ServiceManagerStub aidlServiceManager,
             @Nullable HealthServiceWrapperHidl.Callback hidlRegCallback,
             @NonNull HealthServiceWrapperHidl.IServiceManagerSupplier hidlServiceManagerSupplier,
             @NonNull HealthServiceWrapperHidl.IHealthSupplier hidlHealthSupplier)
             throws RemoteException, NoSuchElementException {
+        try {
+            return new HealthServiceWrapperAidl(aidlRegCallback, aidlServiceManager);
+        } catch (NoSuchElementException e) {
+            // Ignore, try HIDL
+        }
         return new HealthServiceWrapperHidl(
                 hidlRegCallback, hidlServiceManagerSupplier, hidlHealthSupplier);
     }
diff --git a/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java b/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java
new file mode 100644
index 0000000..4f2ed68
--- /dev/null
+++ b/services/core/java/com/android/server/health/HealthServiceWrapperAidl.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2021 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.health;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.health.HealthInfo;
+import android.hardware.health.IHealth;
+import android.os.BatteryManager;
+import android.os.BatteryProperty;
+import android.os.Binder;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.IServiceCallback;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.os.Trace;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Implement {@link HealthServiceWrapper} backed by the AIDL HAL.
+ *
+ * @hide
+ */
+class HealthServiceWrapperAidl extends HealthServiceWrapper {
+    private static final String TAG = "HealthServiceWrapperAidl";
+    @VisibleForTesting static final String SERVICE_NAME = IHealth.DESCRIPTOR + "/default";
+    private final HandlerThread mHandlerThread = new HandlerThread("HealthServiceBinder");
+    private final AtomicReference<IHealth> mLastService = new AtomicReference<>();
+    private final IServiceCallback mServiceCallback = new ServiceCallback();
+    private final HealthRegCallbackAidl mRegCallback;
+
+    /** Stub interface into {@link ServiceManager} for testing. */
+    interface ServiceManagerStub {
+        default @Nullable IHealth waitForDeclaredService(@NonNull String name) {
+            return IHealth.Stub.asInterface(ServiceManager.waitForDeclaredService(name));
+        }
+
+        default void registerForNotifications(
+                @NonNull String name, @NonNull IServiceCallback callback) throws RemoteException {
+            ServiceManager.registerForNotifications(name, callback);
+        }
+    }
+
+    HealthServiceWrapperAidl(
+            @Nullable HealthRegCallbackAidl regCallback, @NonNull ServiceManagerStub serviceManager)
+            throws RemoteException, NoSuchElementException {
+
+        traceBegin("HealthInitGetServiceAidl");
+        IHealth newService;
+        try {
+            newService = serviceManager.waitForDeclaredService(SERVICE_NAME);
+        } finally {
+            traceEnd();
+        }
+        if (newService == null) {
+            throw new NoSuchElementException(
+                    "IHealth service instance isn't available. Perhaps no permission?");
+        }
+        mLastService.set(newService);
+        mRegCallback = regCallback;
+        if (mRegCallback != null) {
+            mRegCallback.onRegistration(null /* oldService */, newService);
+        }
+
+        traceBegin("HealthInitRegisterNotificationAidl");
+        mHandlerThread.start();
+        try {
+            serviceManager.registerForNotifications(SERVICE_NAME, mServiceCallback);
+        } finally {
+            traceEnd();
+        }
+        Slog.i(TAG, "health: HealthServiceWrapper listening to AIDL HAL");
+    }
+
+    @Override
+    @VisibleForTesting
+    public HandlerThread getHandlerThread() {
+        return mHandlerThread;
+    }
+
+    @Override
+    public int getProperty(int id, BatteryProperty prop) throws RemoteException {
+        traceBegin("HealthGetPropertyAidl");
+        try {
+            return getPropertyInternal(id, prop);
+        } finally {
+            traceEnd();
+        }
+    }
+
+    private int getPropertyInternal(int id, BatteryProperty prop) throws RemoteException {
+        IHealth service = mLastService.get();
+        if (service == null) throw new RemoteException("no health service");
+        try {
+            switch (id) {
+                case BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER:
+                    prop.setLong(service.getChargeCounterUah());
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_CURRENT_NOW:
+                    prop.setLong(service.getCurrentNowMicroamps());
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE:
+                    prop.setLong(service.getCurrentAverageMicroamps());
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_CAPACITY:
+                    prop.setLong(service.getCapacity());
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_STATUS:
+                    prop.setLong(service.getChargeStatus());
+                    break;
+                case BatteryManager.BATTERY_PROPERTY_ENERGY_COUNTER:
+                    prop.setLong(service.getEnergyCounterNwh());
+                    break;
+            }
+        } catch (UnsupportedOperationException e) {
+            // Leave prop untouched.
+            return -1;
+        } catch (ServiceSpecificException e) {
+            // Leave prop untouched.
+            return -2;
+        }
+        // throws RemoteException as-is. BatteryManager wraps it into a RuntimeException
+        // and throw it to apps.
+
+        // If no error, return 0.
+        return 0;
+    }
+
+    @Override
+    public void scheduleUpdate() throws RemoteException {
+        getHandlerThread()
+                .getThreadHandler()
+                .post(
+                        () -> {
+                            traceBegin("HealthScheduleUpdate");
+                            try {
+                                IHealth service = mLastService.get();
+                                if (service == null) {
+                                    Slog.e(TAG, "no health service");
+                                    return;
+                                }
+                                service.update();
+                            } catch (RemoteException | ServiceSpecificException ex) {
+                                Slog.e(TAG, "Cannot call update on health AIDL HAL", ex);
+                            } finally {
+                                traceEnd();
+                            }
+                        });
+    }
+
+    @Override
+    public HealthInfo getHealthInfo() throws RemoteException {
+        IHealth service = mLastService.get();
+        if (service == null) return null;
+        try {
+            return service.getHealthInfo();
+        } catch (UnsupportedOperationException | ServiceSpecificException ex) {
+            return null;
+        }
+    }
+
+    private static void traceBegin(String name) {
+        Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, name);
+    }
+
+    private static void traceEnd() {
+        Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
+    }
+
+    private class ServiceCallback extends IServiceCallback.Stub {
+        @Override
+        public void onRegistration(String name, @NonNull final IBinder newBinder)
+                throws RemoteException {
+            if (!SERVICE_NAME.equals(name)) return;
+            // This runnable only runs on mHandlerThread and ordering is ensured, hence
+            // no locking is needed inside the runnable.
+            getHandlerThread()
+                    .getThreadHandler()
+                    .post(
+                            () -> {
+                                IHealth newService =
+                                        IHealth.Stub.asInterface(Binder.allowBlocking(newBinder));
+                                IHealth oldService = mLastService.getAndSet(newService);
+                                IBinder oldBinder =
+                                        oldService != null ? oldService.asBinder() : null;
+                                if (Objects.equals(newBinder, oldBinder)) return;
+
+                                Slog.i(TAG, "New health AIDL HAL service registered");
+                                mRegCallback.onRegistration(oldService, newService);
+                            });
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
new file mode 100644
index 0000000..05e1bdd
--- /dev/null
+++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
@@ -0,0 +1,476 @@
+/*
+ * Copyright (C) 2021 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.inputmethod;
+
+import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+
+import static com.android.server.inputmethod.InputMethodManagerService.MSG_INITIALIZE_IME;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManagerInternal;
+import android.content.res.Resources;
+import android.inputmethodservice.InputMethodService;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.Trace;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.util.ArrayMap;
+import android.util.Slog;
+import android.view.IWindowManager;
+import android.view.WindowManager;
+import android.view.inputmethod.InputMethod;
+import android.view.inputmethod.InputMethodInfo;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.inputmethod.InputBindResult;
+import com.android.internal.inputmethod.UnbindReason;
+import com.android.internal.view.IInputMethod;
+import com.android.server.wm.WindowManagerInternal;
+
+/**
+ * A controller managing the state of the input method binding.
+ */
+final class InputMethodBindingController {
+    static final boolean DEBUG = false;
+    private static final String TAG = InputMethodBindingController.class.getSimpleName();
+
+    @NonNull private final InputMethodManagerService mService;
+    @NonNull private final Context mContext;
+    @NonNull private final ArrayMap<String, InputMethodInfo> mMethodMap;
+    @NonNull private final InputMethodUtils.InputMethodSettings mSettings;
+    @NonNull private final PackageManagerInternal mPackageManagerInternal;
+    @NonNull private final IWindowManager mIWindowManager;
+    @NonNull private final WindowManagerInternal mWindowManagerInternal;
+    @NonNull private final Resources mRes;
+
+    private long mLastBindTime;
+    private boolean mHasConnection;
+    @Nullable private String mCurId;
+    @Nullable private String mSelectedMethodId;
+    @Nullable private Intent mCurIntent;
+    @Nullable private IInputMethod mCurMethod;
+    private int mCurMethodUid = Process.INVALID_UID;
+    private IBinder mCurToken;
+    private int mCurSeq;
+    private boolean mVisibleBound;
+
+    /**
+     * Binding flags for establishing connection to the {@link InputMethodService}.
+     */
+    private static final int IME_CONNECTION_BIND_FLAGS =
+            Context.BIND_AUTO_CREATE
+                    | Context.BIND_NOT_VISIBLE
+                    | Context.BIND_NOT_FOREGROUND
+                    | Context.BIND_IMPORTANT_BACKGROUND;
+    /**
+     * Binding flags for establishing connection to the {@link InputMethodService} when
+     * config_killableInputMethods is enabled.
+     */
+    private static final int IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS =
+            Context.BIND_AUTO_CREATE
+                    | Context.BIND_REDUCTION_FLAGS;
+    /**
+     * Binding flags used only while the {@link InputMethodService} is showing window.
+     */
+    private static final int IME_VISIBLE_BIND_FLAGS =
+            Context.BIND_AUTO_CREATE
+                    | Context.BIND_TREAT_LIKE_ACTIVITY
+                    | Context.BIND_FOREGROUND_SERVICE
+                    | Context.BIND_INCLUDE_CAPABILITIES
+                    | Context.BIND_SHOWING_UI
+                    | Context.BIND_SCHEDULE_LIKE_TOP_APP;
+
+    /**
+     * Binding flags for establishing connection to the {@link InputMethodService}.
+     *
+     * <p>
+     * This defaults to {@link InputMethodBindingController#IME_CONNECTION_BIND_FLAGS} unless
+     * config_killableInputMethods is enabled, in which case this takes the value of
+     * {@link InputMethodBindingController#IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS}.
+     */
+    private final int mImeConnectionBindFlags;
+
+    InputMethodBindingController(@NonNull InputMethodManagerService service) {
+        mService = service;
+        mContext = mService.mContext;
+        mMethodMap = mService.mMethodMap;
+        mSettings = mService.mSettings;
+        mPackageManagerInternal = mService.mPackageManagerInternal;
+        mIWindowManager = mService.mIWindowManager;
+        mWindowManagerInternal = mService.mWindowManagerInternal;
+        mRes = mService.mRes;
+
+        // If configured, use low priority flags to make the IME killable by the lowmemorykiller
+        final boolean lowerIMEPriority = mRes.getBoolean(
+                com.android.internal.R.bool.config_killableInputMethods);
+
+        if (lowerIMEPriority) {
+            mImeConnectionBindFlags =
+                    InputMethodBindingController.IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS;
+        } else {
+            mImeConnectionBindFlags = InputMethodBindingController.IME_CONNECTION_BIND_FLAGS;
+        }
+    }
+
+    /**
+     * Time that we last initiated a bind to the input method, to determine
+     * if we should try to disconnect and reconnect to it.
+     */
+    long getLastBindTime() {
+        return mLastBindTime;
+    }
+
+    /**
+     * Set to true if our ServiceConnection is currently actively bound to
+     * a service (whether or not we have gotten its IBinder back yet).
+     */
+    boolean hasConnection() {
+        return mHasConnection;
+    }
+
+    /**
+     * Id obtained with {@link InputMethodInfo#getId()} for the input method that we are currently
+     * connected to or in the process of connecting to.
+     *
+     * <p>This can be {@code null} when no input method is connected.</p>
+     *
+     * @see #getSelectedMethodId()
+     */
+    @Nullable
+    String getCurId() {
+        return mCurId;
+    }
+
+    /**
+     * Id obtained with {@link InputMethodInfo#getId()} for the currently selected input method.
+     * This is to be synchronized with the secure settings keyed with
+     * {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD}.
+     *
+     * <p>This can be transiently {@code null} when the system is re-initializing input method
+     * settings, e.g., the system locale is just changed.</p>
+     *
+     * <p>Note that {@link #getCurId()} is used to track which IME is being connected to
+     * {@link com.android.server.inputmethod.InputMethodManagerService}.</p>
+     *
+     * @see #getCurId()
+     */
+    @Nullable
+    String getSelectedMethodId() {
+        return mSelectedMethodId;
+    }
+
+    void setSelectedMethodId(@Nullable String selectedMethodId) {
+        mSelectedMethodId = selectedMethodId;
+    }
+
+    /**
+     * The token we have made for the currently active input method, to
+     * identify it in the future.
+     */
+    IBinder getCurToken() {
+        return mCurToken;
+    }
+
+    /**
+     * The Intent used to connect to the current input method.
+     */
+    @Nullable
+    Intent getCurIntent() {
+        return mCurIntent;
+    }
+
+    /**
+     * The current binding sequence number, incremented every time there is
+     * a new bind performed.
+     */
+    int getSequenceNumber() {
+        return mCurSeq;
+    }
+
+    /**
+     * Increase the current binding sequence number by one.
+     * Reset to 1 on overflow.
+     */
+    void advanceSequenceNumber() {
+        mCurSeq += 1;
+        if (mCurSeq <= 0) {
+            mCurSeq = 1;
+        }
+    }
+
+    /**
+     * If non-null, this is the input method service we are currently connected
+     * to.
+     */
+    @Nullable
+    IInputMethod getCurMethod() {
+        return mCurMethod;
+    }
+
+    /**
+     * If not {@link Process#INVALID_UID}, then the UID of {@link #getCurIntent()}.
+     */
+    int getCurMethodUid() {
+        return mCurMethodUid;
+    }
+
+    /**
+     * Indicates whether {@link #getVisibleConnection} is currently in use.
+     */
+    boolean isVisibleBound() {
+        return mVisibleBound;
+    }
+
+    /**
+     * Used to bring IME service up to visible adjustment while it is being shown.
+     */
+    @NonNull
+    ServiceConnection getVisibleConnection() {
+        return mVisibleConnection;
+    }
+
+    private final ServiceConnection mVisibleConnection = new ServiceConnection() {
+        @Override public void onBindingDied(ComponentName name) {
+            synchronized (mMethodMap) {
+                if (mVisibleBound) {
+                    unbindVisibleConnectionLocked();
+                }
+            }
+        }
+
+        @Override public void onServiceConnected(ComponentName name, IBinder service) {
+        }
+
+        @Override public void onServiceDisconnected(ComponentName name) {
+        }
+    };
+
+    /**
+     * Used to bind the IME while it is not currently being shown.
+     */
+    private final ServiceConnection mMainConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.onServiceConnected");
+            synchronized (mMethodMap) {
+                if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
+                    mCurMethod = IInputMethod.Stub.asInterface(service);
+                    updateCurrentMethodUidLocked();
+                    if (mCurToken == null) {
+                        Slog.w(TAG, "Service connected without a token!");
+                        unbindCurrentMethodLocked();
+                        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+                        return;
+                    }
+                    if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
+                    // Dispatch display id for InputMethodService to update context display.
+                    mService.executeOrSendMessage(mCurMethod,
+                            mService.mCaller.obtainMessageIOO(MSG_INITIALIZE_IME,
+                                    mMethodMap.get(mSelectedMethodId).getConfigChanges(),
+                                    mCurMethod, mCurToken));
+                    mService.scheduleNotifyImeUidToAudioService(mCurMethodUid);
+                    mService.reRequestCurrentClientSessionLocked();
+                }
+            }
+            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+        }
+
+        @GuardedBy("mMethodMap")
+        private void updateCurrentMethodUidLocked() {
+            final String curMethodPackage = mCurIntent.getComponent().getPackageName();
+            final int curMethodUid = mPackageManagerInternal.getPackageUid(
+                    curMethodPackage, 0 /* flags */, mSettings.getCurrentUserId());
+            if (curMethodUid < 0) {
+                Slog.e(TAG, "Failed to get UID for package=" + curMethodPackage);
+                mCurMethodUid = Process.INVALID_UID;
+            } else {
+                mCurMethodUid = curMethodUid;
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(@NonNull ComponentName name) {
+            // Note that mContext.unbindService(this) does not trigger this.  Hence if we are
+            // here the
+            // disconnection is not intended by IMMS (e.g. triggered because the current IMS
+            // crashed),
+            // which is irregular but can eventually happen for everyone just by continuing
+            // using the
+            // device.  Thus it is important to make sure that all the internal states are
+            // properly
+            // refreshed when this method is called back.  Running
+            //    adb install -r <APK that implements the current IME>
+            // would be a good way to trigger such a situation.
+            synchronized (mMethodMap) {
+                if (DEBUG) {
+                    Slog.v(TAG, "Service disconnected: " + name + " mCurIntent=" + mCurIntent);
+                }
+                if (mCurMethod != null && mCurIntent != null
+                        && name.equals(mCurIntent.getComponent())) {
+                    // We consider this to be a new bind attempt, since the system
+                    // should now try to restart the service for us.
+                    mLastBindTime = SystemClock.uptimeMillis();
+                    mService.clearClientSessionsLocked();
+                    mService.clearInputShowRequestLocked();
+                    mService.unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME);
+                }
+            }
+        }
+    };
+
+    @GuardedBy("mMethodMap")
+    void unbindCurrentMethodLocked() {
+        if (mVisibleBound) {
+            unbindVisibleConnectionLocked();
+        }
+
+        if (mHasConnection) {
+            unbindMainConnectionLocked();
+        }
+
+        if (mCurToken != null) {
+            removeCurrentTokenLocked();
+            mService.resetSystemUiLocked();
+        }
+
+        mCurId = null;
+        mService.clearClientSessionsLocked();
+    }
+
+    @GuardedBy("mMethodMap")
+    void clearCurMethodLocked() {
+        mCurMethod = null;
+        mCurMethodUid = Process.INVALID_UID;
+    }
+
+    @GuardedBy("mMethodMap")
+    private void removeCurrentTokenLocked() {
+        int curTokenDisplayId = mService.getCurTokenDisplayId();
+
+        if (DEBUG) {
+            Slog.v(TAG,
+                    "Removing window token: " + mCurToken + " for display: " + curTokenDisplayId);
+        }
+        mWindowManagerInternal.removeWindowToken(mCurToken, false /* removeWindows */,
+                false /* animateExit */, curTokenDisplayId);
+        mCurToken = null;
+    }
+
+    @GuardedBy("mMethodMap")
+    @NonNull
+    InputBindResult bindCurrentMethodLocked(int displayIdToShowIme) {
+        InputMethodInfo info = mMethodMap.get(mSelectedMethodId);
+        if (info == null) {
+            throw new IllegalArgumentException("Unknown id: " + mSelectedMethodId);
+        }
+
+        mCurIntent = createImeBindingIntent(info.getComponent());
+
+        if (bindCurrentInputMethodServiceMainConnectionLocked()) {
+            mCurId = info.getId();
+            mLastBindTime = SystemClock.uptimeMillis();
+
+            addFreshWindowTokenLocked(displayIdToShowIme);
+            return new InputBindResult(
+                    InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING,
+                    null, null, mCurId, mCurSeq, false);
+        }
+
+        Slog.w(InputMethodManagerService.TAG,
+                "Failure connecting to input method service: " + mCurIntent);
+        mCurIntent = null;
+        return InputBindResult.IME_NOT_CONNECTED;
+    }
+
+    @NonNull
+    private Intent createImeBindingIntent(ComponentName component) {
+        Intent intent = new Intent(InputMethod.SERVICE_INTERFACE);
+        intent.setComponent(component);
+        intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
+                com.android.internal.R.string.input_method_binding_label);
+        intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
+                mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS),
+                PendingIntent.FLAG_IMMUTABLE));
+        return intent;
+    }
+
+    @GuardedBy("mMethodMap")
+    private void addFreshWindowTokenLocked(int displayIdToShowIme) {
+        mCurToken = new Binder();
+
+        mService.setCurTokenDisplayId(displayIdToShowIme);
+
+        try {
+            if (DEBUG) {
+                Slog.v(TAG, "Adding window token: " + mCurToken + " for display: "
+                        + displayIdToShowIme);
+            }
+            mIWindowManager.addWindowToken(mCurToken, WindowManager.LayoutParams.TYPE_INPUT_METHOD,
+                    displayIdToShowIme, null /* options */);
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Could not add window token " + mCurToken + " for display "
+                    + displayIdToShowIme, e);
+        }
+    }
+
+    @GuardedBy("mMethodMap")
+    void unbindMainConnectionLocked() {
+        mContext.unbindService(mMainConnection);
+        mHasConnection = false;
+    }
+
+    @GuardedBy("mMethodMap")
+    void unbindVisibleConnectionLocked() {
+        mContext.unbindService(mVisibleConnection);
+        mVisibleBound = false;
+    }
+
+    @GuardedBy("mMethodMap")
+    private boolean bindCurrentInputMethodServiceLocked(ServiceConnection conn, int flags) {
+        if (mCurIntent == null || conn == null) {
+            Slog.e(TAG, "--- bind failed: service = " + mCurIntent + ", conn = " + conn);
+            return false;
+        }
+        return mContext.bindServiceAsUser(mCurIntent, conn, flags,
+                new UserHandle(mSettings.getCurrentUserId()));
+    }
+
+    @GuardedBy("mMethodMap")
+    boolean bindCurrentInputMethodServiceVisibleConnectionLocked() {
+        mVisibleBound = bindCurrentInputMethodServiceLocked(mVisibleConnection,
+                IME_VISIBLE_BIND_FLAGS);
+        return mVisibleBound;
+    }
+
+    @GuardedBy("mMethodMap")
+    boolean bindCurrentInputMethodServiceMainConnectionLocked() {
+        mHasConnection = bindCurrentInputMethodServiceLocked(mMainConnection,
+                mImeConnectionBindFlags);
+        return mHasConnection;
+    }
+
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index d74b3d7..c879e3d 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -72,13 +72,11 @@
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
-import android.content.ComponentName;
 import android.content.ContentProvider;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
@@ -208,7 +206,7 @@
  * This class provides a system service that manages input methods.
  */
 public class InputMethodManagerService extends IInputMethodManager.Stub
-        implements ServiceConnection, Handler.Callback {
+        implements Handler.Callback {
     static final boolean DEBUG = false;
     static final String TAG = "InputMethodManagerService";
     public static final String PROTO_ARG = "--proto";
@@ -261,44 +259,6 @@
     private static final String HANDLER_THREAD_NAME = "android.imms";
 
     /**
-     * Binding flags for establishing connection to the {@link InputMethodService}.
-     */
-    private static final int IME_CONNECTION_BIND_FLAGS =
-            Context.BIND_AUTO_CREATE
-            | Context.BIND_NOT_VISIBLE
-            | Context.BIND_NOT_FOREGROUND
-            | Context.BIND_IMPORTANT_BACKGROUND;
-
-    /**
-     * Binding flags for establishing connection to the {@link InputMethodService} when
-     * config_killableInputMethods is enabled.
-     */
-    private static final int IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS =
-            Context.BIND_AUTO_CREATE
-            | Context.BIND_REDUCTION_FLAGS;
-
-    /**
-     * Binding flags for establishing connection to the {@link InputMethodService}.
-     *
-     * <p>
-     * This defaults to {@link #IME_CONNECTION_BIND_FLAGS} unless config_killableInputMethods is
-     * enabled, in which case this takes the value of
-     * {@link #IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS}.
-     */
-    private final int mImeConnectionBindFlags;
-
-    /**
-     * Binding flags used only while the {@link InputMethodService} is showing window.
-     */
-    private static final int IME_VISIBLE_BIND_FLAGS =
-            Context.BIND_AUTO_CREATE
-            | Context.BIND_TREAT_LIKE_ACTIVITY
-            | Context.BIND_FOREGROUND_SERVICE
-            | Context.BIND_INCLUDE_CAPABILITIES
-            | Context.BIND_SHOWING_UI
-            | Context.BIND_SCHEDULE_LIKE_TOP_APP;
-
-    /**
      * A protected broadcast intent action for internal use for {@link PendingIntent} in
      * the notification.
      */
@@ -321,11 +281,11 @@
     final boolean mHasFeature;
     private final ArrayMap<String, List<InputMethodSubtype>> mAdditionalSubtypeMap =
             new ArrayMap<>();
-    private final boolean mIsLowRam;
     private final AppOpsManager mAppOpsManager;
     private final UserManager mUserManager;
     private final UserManagerInternal mUserManagerInternal;
     private final InputMethodMenuController mMenuController;
+    private final InputMethodBindingController mBindingController;
 
     /**
      * Cache the result of {@code LocalServices.getService(AudioManagerInternal.class)}.
@@ -351,31 +311,20 @@
     @GuardedBy("mMethodMap")
     private int mMethodMapUpdateCount = 0;
 
-    // Used to bring IME service up to visible adjustment while it is being shown.
-    final ServiceConnection mVisibleConnection = new ServiceConnection() {
-        @Override public void onBindingDied(ComponentName name) {
-            synchronized (mMethodMap) {
-                if (mVisibleBound) {
-                    mContext.unbindService(mVisibleConnection);
-                    mVisibleBound = false;
-                }
-            }
-        }
-
-        @Override public void onServiceConnected(ComponentName name, IBinder service) {
-        }
-
-        @Override public void onServiceDisconnected(ComponentName name) {
-        }
-    };
-    boolean mVisibleBound = false;
+    /**
+     * Indicates whether {@link InputMethodBindingController#getVisibleConnection} is currently
+     * in use.
+     */
+    private boolean isVisibleBound() {
+        return mBindingController.isVisibleBound();
+    }
 
     // Ongoing notification
     private NotificationManager mNotificationManager;
     KeyguardManager mKeyguardManager;
     private @Nullable StatusBarManagerService mStatusBar;
-    private Notification.Builder mImeSwitcherNotification;
-    private PendingIntent mImeSwitchPendingIntent;
+    private final Notification.Builder mImeSwitcherNotification;
+    private final PendingIntent mImeSwitchPendingIntent;
     private boolean mShowOngoingImeSwitcherForPhones;
     private boolean mNotificationShown;
 
@@ -463,25 +412,41 @@
 
     /**
      * Id obtained with {@link InputMethodInfo#getId()} for the currently selected input method.
-     * method.  This is to be synchronized with the secure settings keyed with
+     * This is to be synchronized with the secure settings keyed with
      * {@link Settings.Secure#DEFAULT_INPUT_METHOD}.
      *
      * <p>This can be transiently {@code null} when the system is re-initializing input method
      * settings, e.g., the system locale is just changed.</p>
      *
-     * <p>Note that {@link #mCurId} is used to track which IME is being connected to
-     * {@link InputMethodManagerService}.</p>
+     * <p>Note that {@link InputMethodBindingController#getCurId()} is used to track which IME is
+     * being connected to {@link InputMethodManagerService}.</p>
      *
-     * @see #mCurId
+     * @see InputMethodBindingController#getCurId()
      */
     @Nullable
-    String mCurMethodId;
+    private String getSelectedMethodId() {
+        return mBindingController.getSelectedMethodId();
+    }
+
+    private void setSelectedMethodId(@Nullable String selectedMethodId) {
+        mBindingController.setSelectedMethodId(selectedMethodId);
+    }
 
     /**
      * The current binding sequence number, incremented every time there is
      * a new bind performed.
      */
-    int mCurSeq;
+    private int getSequenceNumber() {
+        return mBindingController.getSequenceNumber();
+    }
+
+    /**
+     * Increase the current binding sequence number by one.
+     * Reset to 1 on overflow.
+     */
+    private void advanceSequenceNumber() {
+        mBindingController.advanceSequenceNumber();
+    }
 
     /**
      * {@code true} if the Ime policy has been set to {@link WindowManager#DISPLAY_IME_POLICY_HIDE}.
@@ -493,7 +458,7 @@
     /**
      * The client that is currently bound to an input method.
      */
-    ClientState mCurClient;
+    private ClientState mCurClient;
 
     /**
      * The last window token that we confirmed to be focused.  This is always updated upon reports
@@ -538,19 +503,18 @@
      *
      * <p>This can be {@code null} when no input method is connected.</p>
      *
-     * @see #mCurMethodId
+     * @see #getSelectedMethodId()
      */
     @Nullable
-    String mCurId;
+    private String getCurId() {
+        return mBindingController.getCurId();
+    }
 
     /**
      * The current subtype of the current input method.
      */
     private InputMethodSubtype mCurrentSubtype;
 
-    // Was the keyguard locked when this client became current?
-    private boolean mCurClientInKeyguard;
-
     /**
      * {@code true} if the IME has not been mostly hidden via {@link android.view.InsetsController}
      */
@@ -560,12 +524,14 @@
      * Set to true if our ServiceConnection is currently actively bound to
      * a service (whether or not we have gotten its IBinder back yet).
      */
-    boolean mHaveConnection;
+    private boolean hasConnection() {
+        return mBindingController.hasConnection();
+    }
 
     /**
      * Set if the client has asked for the input method to be shown.
      */
-    boolean mShowRequested;
+    private boolean mShowRequested;
 
     /**
      * Set if we were explicitly told to show the input method.
@@ -580,7 +546,7 @@
     /**
      * Set if we last told the input method to show itself.
      */
-    boolean mInputShown;
+    private boolean mInputShown;
 
     /**
      * {@code true} if the current input method is in fullscreen mode.
@@ -590,17 +556,30 @@
     /**
      * The Intent used to connect to the current input method.
      */
-    Intent mCurIntent;
+    @Nullable
+    private Intent getCurIntent() {
+        return mBindingController.getCurIntent();
+    }
 
     /**
      * The token we have made for the currently active input method, to
      * identify it in the future.
      */
-    IBinder mCurToken;
+    private IBinder getCurToken() {
+        return mBindingController.getCurToken();
+    }
 
     /**
      * The displayId of current active input method.
      */
+    int getCurTokenDisplayId() {
+        return mCurTokenDisplayId;
+    }
+
+    void setCurTokenDisplayId(int curTokenDisplayId) {
+        mCurTokenDisplayId = curTokenDisplayId;
+    }
+
     int mCurTokenDisplayId = INVALID_DISPLAY;
 
     /**
@@ -622,18 +601,25 @@
      * If non-null, this is the input method service we are currently connected
      * to.
      */
-    IInputMethod mCurMethod;
+    @Nullable
+    private IInputMethod getCurMethod() {
+        return mBindingController.getCurMethod();
+    }
 
     /**
-     * If not {@link Process#INVALID_UID}, then the UID of {@link #mCurIntent}.
+     * If not {@link Process#INVALID_UID}, then the UID of {@link #getCurIntent()}.
      */
-    int mCurMethodUid = Process.INVALID_UID;
+    private int getCurMethodUid() {
+        return mBindingController.getCurMethodUid();
+    }
 
     /**
      * Time that we last initiated a bind to the input method, to determine
      * if we should try to disconnect and reconnect to it.
      */
-    long mLastBindTime;
+    private long getLastBindTime() {
+        return mBindingController.getLastBindTime();
+    }
 
     /**
      * Have we called mCurMethod.bindInput()?
@@ -651,7 +637,7 @@
      */
     boolean mIsInteractive = true;
 
-    private IPlatformCompat mPlatformCompat;
+    private final IPlatformCompat mPlatformCompat;
 
     int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
 
@@ -674,7 +660,7 @@
      * </dd>
      * </dl>
      * <em>Do not update this value outside of {@link #setImeWindowStatus(IBinder, int, int)} and
-     * {@link #unbindCurrentMethodLocked()}.</em>
+     * {@link InputMethodBindingController#unbindCurrentMethodLocked()}.</em>
      */
     int mImeWindowVis;
 
@@ -761,7 +747,7 @@
     private final WeakHashMap<IBinder, IBinder> mImeTargetWindowMap = new WeakHashMap<>();
 
     private static final class SoftInputShowHideHistory {
-        private Entry[] mEntries = new Entry[16];
+        private final Entry[] mEntries = new Entry[16];
         private int mNextIndex = 0;
         private static final AtomicInteger sSequenceNumber = new AtomicInteger(0);
 
@@ -1515,7 +1501,7 @@
     private UserSwitchHandlerTask mUserSwitchHandlerTask;
 
     public static final class Lifecycle extends SystemService {
-        private InputMethodManagerService mService;
+        private final InputMethodManagerService mService;
 
         public Lifecycle(Context context) {
             super(context);
@@ -1613,13 +1599,9 @@
         mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
-        mImeDisplayValidator = displayId -> mWindowManagerInternal.getDisplayImePolicy(displayId);
-        mCaller = new HandlerCaller(context, thread.getLooper(), new HandlerCaller.Callback() {
-            @Override
-            public void executeMessage(Message msg) {
-                handleMessage(msg);
-            }
-        }, true /*asyncHandler*/);
+        mImeDisplayValidator = mWindowManagerInternal::getDisplayImePolicy;
+        mCaller = new HandlerCaller(context, thread.getLooper(), this::handleMessage,
+                true /*asyncHandler*/);
         mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
         mUserManager = mContext.getSystemService(UserManager.class);
         mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
@@ -1628,7 +1610,6 @@
         mPlatformCompat = IPlatformCompat.Stub.asInterface(
                 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
         mSlotIme = mContext.getString(com.android.internal.R.string.status_bar_ime);
-        mIsLowRam = ActivityManager.isLowRamDeviceStatic();
 
         Bundle extras = new Bundle();
         extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
@@ -1669,22 +1650,14 @@
         mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
                 mSettings, context);
         mMenuController = new InputMethodMenuController(this);
-
-        // If configured, use low priority flags to make the IME killable by the lowmemorykiller
-        final boolean lowerIMEPriority = mRes.getBoolean(
-                com.android.internal.R.bool.config_killableInputMethods);
-
-        if (lowerIMEPriority) {
-            mImeConnectionBindFlags = IME_CONNECTION_LOW_PRIORITY_BIND_FLAGS;
-        } else {
-            mImeConnectionBindFlags = IME_CONNECTION_BIND_FLAGS;
-        }
+        mBindingController = new InputMethodBindingController(this);
     }
 
     @GuardedBy("mMethodMap")
     private void resetDefaultImeLocked(Context context) {
         // Do not reset the default (current) IME when it is a 3rd-party IME
-        if (mCurMethodId != null && !mMethodMap.get(mCurMethodId).isSystem()) {
+        String selectedMethodId = getSelectedMethodId();
+        if (selectedMethodId != null && !mMethodMap.get(selectedMethodId).isSystem()) {
             return;
         }
         final List<InputMethodInfo> suitableImes = InputMethodUtils.getDefaultEnabledImes(
@@ -1799,9 +1772,7 @@
                 mKeyguardManager = mContext.getSystemService(KeyguardManager.class);
                 mNotificationManager = mContext.getSystemService(NotificationManager.class);
                 mStatusBar = statusBar;
-                if (mStatusBar != null) {
-                    mStatusBar.setIconVisibility(mSlotIme, false);
-                }
+                hideStatusBarIconLocked();
                 updateSystemUiLocked(mImeWindowVis, mBackDisposition);
                 mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
                         com.android.internal.R.bool.show_ongoing_ime_switcher);
@@ -1893,7 +1864,7 @@
         if (token == null) {
             throw new InvalidParameterException("token must not be null.");
         }
-        if (token != mCurToken) {
+        if (token != getCurToken()) {
             Slog.e(TAG, "Ignoring " + Debug.getCaller() + " due to an invalid token."
                     + " uid:" + Binder.getCallingUid() + " token:" + token);
             return false;
@@ -1901,17 +1872,6 @@
         return true;
     }
 
-    @GuardedBy("mMethodMap")
-    private boolean bindCurrentInputMethodServiceLocked(
-            Intent service, ServiceConnection conn, int flags) {
-        if (service == null || conn == null) {
-            Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn);
-            return false;
-        }
-        return mContext.bindServiceAsUser(service, conn, flags,
-                new UserHandle(mSettings.getCurrentUserId()));
-    }
-
     @Override
     public List<InputMethodInfo> getInputMethodList(@UserIdInt int userId) {
         if (UserHandle.getCallingUserId() != userId) {
@@ -1992,14 +1952,15 @@
     @GuardedBy("mMethodMap")
     private void onCreateInlineSuggestionsRequestLocked(@UserIdInt int userId,
             InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback callback) {
-        final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
+        final InputMethodInfo imi = mMethodMap.get(getSelectedMethodId());
         try {
+            IInputMethod curMethod = getCurMethod();
             if (userId == mSettings.getCurrentUserId() && imi != null
-                    && imi.isInlineSuggestionsEnabled() && mCurMethod != null) {
-                executeOrSendMessage(mCurMethod,
-                        mCaller.obtainMessageOOO(MSG_INLINE_SUGGESTIONS_REQUEST, mCurMethod,
+                    && imi.isInlineSuggestionsEnabled() && curMethod != null) {
+                executeOrSendMessage(curMethod,
+                        mCaller.obtainMessageOOO(MSG_INLINE_SUGGESTIONS_REQUEST, curMethod,
                                 requestInfo, new InlineSuggestionsRequestCallbackDecorator(callback,
-                                        imi.getPackageName(), mCurTokenDisplayId, mCurToken,
+                                        imi.getPackageName(), mCurTokenDisplayId, getCurToken(),
                                         this)));
             } else {
                 callback.onInlineSuggestionsUnsupported();
@@ -2135,8 +2096,9 @@
             boolean allowsImplicitlySelectedSubtypes, @UserIdInt int userId) {
         if (userId == mSettings.getCurrentUserId()) {
             final InputMethodInfo imi;
-            if (imiId == null && mCurMethodId != null) {
-                imi = mMethodMap.get(mCurMethodId);
+            String selectedMethodId = getSelectedMethodId();
+            if (imiId == null && selectedMethodId != null) {
+                imi = mMethodMap.get(selectedMethodId);
             } else {
                 imi = mMethodMap.get(imiId);
             }
@@ -2233,9 +2195,10 @@
                             mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_REMOVE_CLIENT);
                     if (mBoundToMethod) {
                         mBoundToMethod = false;
-                        if (mCurMethod != null) {
-                            executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
-                                    MSG_UNBIND_INPUT, mCurMethod));
+                        IInputMethod curMethod = getCurMethod();
+                        if (curMethod != null) {
+                            executeOrSendMessage(curMethod, mCaller.obtainMessageO(
+                                    MSG_UNBIND_INPUT, curMethod));
                         }
                     }
                     mCurClient = null;
@@ -2263,16 +2226,17 @@
                     + mCurClient.client.asBinder());
             if (mBoundToMethod) {
                 mBoundToMethod = false;
-                if (mCurMethod != null) {
-                    executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
-                            MSG_UNBIND_INPUT, mCurMethod));
+                IInputMethod curMethod = getCurMethod();
+                if (curMethod != null) {
+                    executeOrSendMessage(curMethod, mCaller.obtainMessageO(
+                            MSG_UNBIND_INPUT, curMethod));
                 }
             }
 
             scheduleSetActiveToClient(mCurClient, false /* active */, false /* fullscreen */,
                     false /* reportToImeController */);
             executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIIO(
-                    MSG_UNBIND_CLIENT, mCurSeq, unbindClientReason, mCurClient.client));
+                    MSG_UNBIND_CLIENT, getSequenceNumber(), unbindClientReason, mCurClient.client));
             mCurClient.sessionRequested = false;
             mCurClient = null;
 
@@ -2281,6 +2245,12 @@
     }
 
     @GuardedBy("mMethodMap")
+    void clearInputShowRequestLocked() {
+        mShowRequested = mInputShown;
+        mInputShown = false;
+    }
+
+    @GuardedBy("mMethodMap")
     private int getImeShowFlagsLocked() {
         int flags = 0;
         if (mShowForced) {
@@ -2307,16 +2277,18 @@
     @NonNull
     InputBindResult attachNewInputLocked(@StartInputReason int startInputReason, boolean initial) {
         if (!mBoundToMethod) {
-            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
-                    MSG_BIND_INPUT, mCurMethod, mCurClient.binding));
+            IInputMethod curMethod = getCurMethod();
+            executeOrSendMessage(curMethod, mCaller.obtainMessageOO(
+                    MSG_BIND_INPUT, curMethod, mCurClient.binding));
             mBoundToMethod = true;
         }
 
         final Binder startInputToken = new Binder();
-        final StartInputInfo info = new StartInputInfo(mSettings.getCurrentUserId(), mCurToken,
-                mCurTokenDisplayId, mCurId, startInputReason, !initial,
+        final StartInputInfo info = new StartInputInfo(mSettings.getCurrentUserId(), getCurToken(),
+                mCurTokenDisplayId, getCurId(), startInputReason, !initial,
                 UserHandle.getUserId(mCurClient.uid), mCurClient.selfReportedDisplayId,
-                mCurFocusedWindow, mCurAttribute, mCurFocusedWindowSoftInputMode, mCurSeq);
+                mCurFocusedWindow, mCurAttribute, mCurFocusedWindowSoftInputMode,
+                getSequenceNumber());
         mImeTargetWindowMap.put(startInputToken, mCurFocusedWindow);
         mStartInputHistory.addEntry(info);
 
@@ -2327,7 +2299,8 @@
         // INTERACT_ACROSS_USERS(_FULL) permissions, which is actually almost always the case.
         if (mSettings.getCurrentUserId() == UserHandle.getUserId(mCurClient.uid)) {
             mPackageManagerInternal.grantImplicitAccess(mSettings.getCurrentUserId(),
-                    null /* intent */, UserHandle.getAppId(mCurMethodUid), mCurClient.uid, true);
+                    null /* intent */, UserHandle.getAppId(getCurMethodUid()), mCurClient.uid,
+                    true /* direct */);
         }
 
         final SessionState session = mCurClient.curSession;
@@ -2339,12 +2312,14 @@
             showCurrentInputLocked(mCurFocusedWindow, getAppShowFlagsLocked(), null,
                     SoftInputShowHideReason.ATTACH_NEW_INPUT);
         }
-        final InputMethodInfo curInputMethodInfo = mMethodMap.get(mCurId);
+
+        String curId = getCurId();
+        final InputMethodInfo curInputMethodInfo = mMethodMap.get(curId);
         final boolean suppressesSpellChecker =
                 curInputMethodInfo != null && curInputMethodInfo.suppressesSpellChecker();
         return new InputBindResult(InputBindResult.ResultCode.SUCCESS_WITH_IME_SESSION,
                 session.session, (session.channel != null ? session.channel.dup() : null),
-                mCurId, mCurSeq, suppressesSpellChecker);
+                curId, getSequenceNumber(), suppressesSpellChecker);
     }
 
     @GuardedBy("mMethodMap")
@@ -2353,7 +2328,8 @@
             @NonNull EditorInfo attribute, @StartInputFlags int startInputFlags,
             @StartInputReason int startInputReason) {
         // If no method is currently selected, do nothing.
-        if (mCurMethodId == null) {
+        String selectedMethodId = getSelectedMethodId();
+        if (selectedMethodId == null) {
             return InputBindResult.NO_IME;
         }
 
@@ -2362,7 +2338,7 @@
             // party code.
             return new InputBindResult(
                     InputBindResult.ResultCode.ERROR_SYSTEM_NOT_READY,
-                    null, null, mCurMethodId, mCurSeq, false);
+                    null, null, selectedMethodId, getSequenceNumber(), false);
         }
 
         if (!InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, cs.uid,
@@ -2390,24 +2366,11 @@
         mImeHiddenByDisplayPolicy = false;
 
         if (mCurClient != cs) {
-            // Was the keyguard locked when switching over to the new client?
-            mCurClientInKeyguard = isKeyguardLocked();
-            // If the client is changing, we need to switch over to the new
-            // one.
-            unbindCurrentClientLocked(UnbindReason.SWITCH_CLIENT);
-            if (DEBUG) Slog.v(TAG, "switching to client: client="
-                    + cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard);
-
-            // If the screen is on, inform the new client it is active
-            if (mIsInteractive) {
-                scheduleSetActiveToClient(cs, true /* active */, false /* fullscreen */,
-                        false /* reportToImeController */);
-            }
+            prepareClientSwitchLocked(cs);
         }
 
         // Bump up the sequence for this client and attach it.
-        mCurSeq++;
-        if (mCurSeq <= 0) mCurSeq = 1;
+        advanceSequenceNumber();
         mCurClient = cs;
         mCurInputContext = inputContext;
         mCurAttribute = attribute;
@@ -2415,24 +2378,57 @@
         // Check if the input method is changing.
         // We expect the caller has already verified that the client is allowed to access this
         // display ID.
-        if (mCurId != null && mCurId.equals(mCurMethodId)
-                && displayIdToShowIme == mCurTokenDisplayId) {
+        if (isSelectedMethodBound(displayIdToShowIme)) {
             if (cs.curSession != null) {
                 // Fast case: if we are already connected to the input method,
                 // then just return it.
                 return attachNewInputLocked(startInputReason,
                         (startInputFlags & StartInputFlags.INITIAL_CONNECTION) != 0);
             }
-            if (mHaveConnection) {
-                if (mCurMethod != null) {
-                    // Return to client, and we will get back with it when
-                    // we have had a session made for it.
-                    requestClientSessionLocked(cs);
-                    return new InputBindResult(
-                            InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION,
-                            null, null, mCurId, mCurSeq, false);
-                } else if (SystemClock.uptimeMillis()
-                        < (mLastBindTime+TIME_TO_RECONNECT)) {
+
+            InputBindResult bindResult = tryReuseConnectionLocked(cs);
+            if (bindResult != null) {
+                return bindResult;
+            }
+        }
+
+        mBindingController.unbindCurrentMethodLocked();
+
+        return mBindingController.bindCurrentMethodLocked(displayIdToShowIme);
+    }
+
+    private boolean isSelectedMethodBound(int displayIdToShowIme) {
+        String curId = getCurId();
+        return curId != null && curId.equals(getSelectedMethodId())
+                && displayIdToShowIme == mCurTokenDisplayId;
+    }
+
+    @GuardedBy("mMethodMap")
+    private void prepareClientSwitchLocked(ClientState cs) {
+        // If the client is changing, we need to switch over to the new
+        // one.
+        unbindCurrentClientLocked(UnbindReason.SWITCH_CLIENT);
+        // If the screen is on, inform the new client it is active
+        if (mIsInteractive) {
+            scheduleSetActiveToClient(cs, true /* active */, false /* fullscreen */,
+                    false /* reportToImeController */);
+        }
+    }
+
+    @GuardedBy("mMethodMap")
+    @Nullable
+    private InputBindResult tryReuseConnectionLocked(@NonNull ClientState cs) {
+        if (hasConnection()) {
+            if (getCurMethod() != null) {
+                // Return to client, and we will get back with it when
+                // we have had a session made for it.
+                requestClientSessionLocked(cs);
+                return new InputBindResult(
+                        InputBindResult.ResultCode.SUCCESS_WAITING_IME_SESSION,
+                        null, null, getCurId(), getSequenceNumber(), false);
+            } else {
+                long bindingDuration = SystemClock.uptimeMillis() - getLastBindTime();
+                if (bindingDuration < TIME_TO_RECONNECT) {
                     // In this case we have connected to the service, but
                     // don't yet have its interface.  If it hasn't been too
                     // long since we did the connection, we'll return to
@@ -2442,51 +2438,14 @@
                     // to see if we can get back in touch with the service.
                     return new InputBindResult(
                             InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING,
-                            null, null, mCurId, mCurSeq, false);
+                            null, null, getCurId(), getSequenceNumber(), false);
                 } else {
                     EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
-                            mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
+                            getSelectedMethodId(), bindingDuration, 0);
                 }
             }
         }
-
-        InputMethodInfo info = mMethodMap.get(mCurMethodId);
-        if (info == null) {
-            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
-        }
-
-        unbindCurrentMethodLocked();
-
-        mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
-        mCurIntent.setComponent(info.getComponent());
-        mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
-                com.android.internal.R.string.input_method_binding_label);
-        mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
-                mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS),
-                PendingIntent.FLAG_IMMUTABLE));
-
-        if (bindCurrentInputMethodServiceLocked(mCurIntent, this, mImeConnectionBindFlags)) {
-            mLastBindTime = SystemClock.uptimeMillis();
-            mHaveConnection = true;
-            mCurId = info.getId();
-            mCurToken = new Binder();
-            mCurTokenDisplayId = displayIdToShowIme;
-            try {
-                if (DEBUG) {
-                    Slog.v(TAG, "Adding window token: " + mCurToken + " for display: "
-                            + mCurTokenDisplayId);
-                }
-                mIWindowManager.addWindowToken(mCurToken, LayoutParams.TYPE_INPUT_METHOD,
-                        mCurTokenDisplayId, null /* options */);
-            } catch (RemoteException e) {
-            }
-            return new InputBindResult(
-                    InputBindResult.ResultCode.SUCCESS_WAITING_IME_BINDING,
-                    null, null, mCurId, mCurSeq, false);
-        }
-        mCurIntent = null;
-        Slog.w(TAG, "Failure connecting to input method service: " + mCurIntent);
-        return InputBindResult.IME_NOT_CONNECTED;
+        return null;
     }
 
     @FunctionalInterface
@@ -2522,46 +2481,11 @@
     }
 
     @AnyThread
-    private void scheduleNotifyImeUidToAudioService(int uid) {
+    void scheduleNotifyImeUidToAudioService(int uid) {
         mCaller.removeMessages(MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE);
         mCaller.obtainMessageI(MSG_NOTIFY_IME_UID_TO_AUDIO_SERVICE, uid).sendToTarget();
     }
 
-    @Override
-    public void onServiceConnected(ComponentName name, IBinder service) {
-        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.onServiceConnected");
-        synchronized (mMethodMap) {
-            if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
-                mCurMethod = IInputMethod.Stub.asInterface(service);
-                final String curMethodPackage = mCurIntent.getComponent().getPackageName();
-                final int curMethodUid = mPackageManagerInternal.getPackageUid(
-                        curMethodPackage, 0 /* flags */, mSettings.getCurrentUserId());
-                if (curMethodUid < 0) {
-                    Slog.e(TAG, "Failed to get UID for package=" + curMethodPackage);
-                    mCurMethodUid = Process.INVALID_UID;
-                } else {
-                    mCurMethodUid = curMethodUid;
-                }
-                if (mCurToken == null) {
-                    Slog.w(TAG, "Service connected without a token!");
-                    unbindCurrentMethodLocked();
-                    Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-                    return;
-                }
-                if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
-                // Dispatch display id for InputMethodService to update context display.
-                executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(MSG_INITIALIZE_IME,
-                        mMethodMap.get(mCurMethodId).getConfigChanges(), mCurMethod, mCurToken));
-                scheduleNotifyImeUidToAudioService(mCurMethodUid);
-                if (mCurClient != null) {
-                    clearClientSessionLocked(mCurClient);
-                    requestClientSessionLocked(mCurClient);
-                }
-            }
-        }
-        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
-    }
-
     void onSessionCreated(IInputMethod method, IInputMethodSession session,
             InputChannel channel) {
         synchronized (mMethodMap) {
@@ -2570,8 +2494,9 @@
                 channel.dispose();
                 return;
             }
-            if (mCurMethod != null && method != null
-                    && mCurMethod.asBinder() == method.asBinder()) {
+            IInputMethod curMethod = getCurMethod();
+            if (curMethod != null && method != null
+                    && curMethod.asBinder() == method.asBinder()) {
                 if (mCurClient != null) {
                     clearClientSessionLocked(mCurClient);
                     mCurClient.curSession = new SessionState(mCurClient,
@@ -2592,53 +2517,40 @@
     }
 
     @GuardedBy("mMethodMap")
-    void unbindCurrentMethodLocked() {
-        if (mVisibleBound) {
-            mContext.unbindService(mVisibleConnection);
-            mVisibleBound = false;
-        }
-
-        if (mHaveConnection) {
-            mContext.unbindService(this);
-            mHaveConnection = false;
-        }
-
-        if (mCurToken != null) {
-            if (DEBUG) {
-                Slog.v(TAG, "Removing window token: " + mCurToken + " for display: "
-                        + mCurTokenDisplayId);
-            }
-            mWindowManagerInternal.removeWindowToken(mCurToken, false /* removeWindows */,
-                    false /* animateExit */, mCurTokenDisplayId);
-            // Set IME window status as invisible when unbind current method.
-            mImeWindowVis = 0;
-            mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
-            updateSystemUiLocked(mImeWindowVis, mBackDisposition);
-            mCurToken = null;
-            mCurTokenDisplayId = INVALID_DISPLAY;
-            mCurHostInputToken = null;
-        }
-
-        mCurId = null;
-        clearCurMethodLocked();
+    void resetSystemUiLocked() {
+        // Set IME window status as invisible when unbinding current method.
+        mImeWindowVis = 0;
+        mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
+        updateSystemUiLocked(mImeWindowVis, mBackDisposition);
+        mCurTokenDisplayId = INVALID_DISPLAY;
+        mCurHostInputToken = null;
     }
 
     @GuardedBy("mMethodMap")
     void resetCurrentMethodAndClientLocked(@UnbindReason int unbindClientReason) {
-        mCurMethodId = null;
-        unbindCurrentMethodLocked();
+        setSelectedMethodId(null);
+        mBindingController.unbindCurrentMethodLocked();
         unbindCurrentClientLocked(unbindClientReason);
     }
 
     @GuardedBy("mMethodMap")
+    void reRequestCurrentClientSessionLocked() {
+        if (mCurClient != null) {
+            clearClientSessionLocked(mCurClient);
+            requestClientSessionLocked(mCurClient);
+        }
+    }
+
+    @GuardedBy("mMethodMap")
     void requestClientSessionLocked(ClientState cs) {
         if (!cs.sessionRequested) {
             if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
             InputChannel[] channels = InputChannel.openInputChannelPair(cs.toString());
             cs.sessionRequested = true;
-            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOOO(
-                    MSG_CREATE_SESSION, mCurMethod, channels[1],
-                    new MethodCallback(this, mCurMethod, channels[0])));
+            IInputMethod curMethod = getCurMethod();
+            executeOrSendMessage(curMethod, mCaller.obtainMessageOOO(
+                    MSG_CREATE_SESSION, curMethod, channels[1],
+                    new MethodCallback(this, curMethod, channels[0])));
         }
     }
 
@@ -2669,8 +2581,8 @@
     }
 
     @GuardedBy("mMethodMap")
-    void clearCurMethodLocked() {
-        if (mCurMethod != null) {
+    void clearClientSessionsLocked() {
+        if (getCurMethod() != null) {
             final int numClients = mClients.size();
             for (int i = 0; i < numClients; ++i) {
                 clearClientSessionLocked(mClients.valueAt(i));
@@ -2678,41 +2590,13 @@
 
             finishSessionLocked(mEnabledSession);
             mEnabledSession = null;
-            mCurMethod = null;
-            mCurMethodUid = Process.INVALID_UID;
-            scheduleNotifyImeUidToAudioService(mCurMethodUid);
+            mBindingController.clearCurMethodLocked();
+            scheduleNotifyImeUidToAudioService(Process.INVALID_UID);
         }
-        if (mStatusBar != null) {
-            mStatusBar.setIconVisibility(mSlotIme, false);
-        }
+        hideStatusBarIconLocked();
         mInFullscreenMode = false;
     }
 
-    @Override
-    public void onServiceDisconnected(ComponentName name) {
-        // Note that mContext.unbindService(this) does not trigger this.  Hence if we are here the
-        // disconnection is not intended by IMMS (e.g. triggered because the current IMS crashed),
-        // which is irregular but can eventually happen for everyone just by continuing using the
-        // device.  Thus it is important to make sure that all the internal states are properly
-        // refreshed when this method is called back.  Running
-        //    adb install -r <APK that implements the current IME>
-        // would be a good way to trigger such a situation.
-        synchronized (mMethodMap) {
-            if (DEBUG) Slog.v(TAG, "Service disconnected: " + name
-                    + " mCurIntent=" + mCurIntent);
-            if (mCurMethod != null && mCurIntent != null
-                    && name.equals(mCurIntent.getComponent())) {
-                clearCurMethodLocked();
-                // We consider this to be a new bind attempt, since the system
-                // should now try to restart the service for us.
-                mLastBindTime = SystemClock.uptimeMillis();
-                mShowRequested = mInputShown;
-                mInputShown = false;
-                unbindCurrentClientLocked(UnbindReason.DISCONNECT_IME);
-            }
-        }
-    }
-
     @BinderThread
     private void updateStatusIcon(@NonNull IBinder token, String packageName,
             @DrawableRes int iconId) {
@@ -2724,9 +2608,7 @@
             try {
                 if (iconId == 0) {
                     if (DEBUG) Slog.d(TAG, "hide the small icon for the input method");
-                    if (mStatusBar != null) {
-                        mStatusBar.setIconVisibility(mSlotIme, false);
-                    }
+                    hideStatusBarIconLocked();
                 } else if (packageName != null) {
                     if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
                     CharSequence contentDescription = null;
@@ -2753,6 +2635,13 @@
     }
 
     @GuardedBy("mMethodMap")
+    private void hideStatusBarIconLocked() {
+        if (mStatusBar != null) {
+            mStatusBar.setIconVisibility(mSlotIme, false);
+        }
+    }
+
+    @GuardedBy("mMethodMap")
     private boolean shouldShowImeSwitcherLocked(int visibility) {
         if (!mShowOngoingImeSwitcherForPhones) return false;
         if (mMenuController.getSwitchingDialogLocked() != null) return false;
@@ -2816,11 +2705,6 @@
         return false;
     }
 
-    @GuardedBy("mMethodMap")
-    private boolean isKeyguardLocked() {
-        return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
-    }
-
     @BinderThread
     @SuppressWarnings("deprecation")
     private void setImeWindowStatus(@NonNull IBinder token, int vis, int backDisposition) {
@@ -2891,7 +2775,7 @@
     // Caution! This method is called in this class. Handle multi-user carefully
     @GuardedBy("mMethodMap")
     private void updateSystemUiLocked(int vis, int backDisposition) {
-        if (mCurToken == null) {
+        if (getCurToken() == null) {
             return;
         }
         if (DEBUG) {
@@ -2905,20 +2789,16 @@
         // all updateSystemUi happens on system previlege.
         final long ident = Binder.clearCallingIdentity();
         try {
-            // apply policy for binder calls
-            if (vis != 0 && isKeyguardLocked() && !mCurClientInKeyguard) {
-                vis = 0;
-            }
             if (!mCurPerceptible) {
                 vis &= ~InputMethodService.IME_VISIBLE;
             }
             // mImeWindowVis should be updated before calling shouldShowImeSwitcherLocked().
             final boolean needsToShowImeSwitcher = shouldShowImeSwitcherLocked(vis);
             if (mStatusBar != null) {
-                mStatusBar.setImeWindowStatus(mCurTokenDisplayId, mCurToken, vis, backDisposition,
-                        needsToShowImeSwitcher);
+                mStatusBar.setImeWindowStatus(mCurTokenDisplayId, getCurToken(), vis,
+                        backDisposition, needsToShowImeSwitcher);
             }
-            final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
+            final InputMethodInfo imi = mMethodMap.get(getSelectedMethodId());
             if (imi != null && needsToShowImeSwitcher) {
                 // Used to load label
                 final CharSequence title = mRes.getText(
@@ -3026,7 +2906,7 @@
         }
 
         // See if we need to notify a subtype change within the same IME.
-        if (id.equals(mCurMethodId)) {
+        if (id.equals(getSelectedMethodId())) {
             final int subtypeCount = info.getSubtypeCount();
             if (subtypeCount <= 0) {
                 return;
@@ -3047,10 +2927,11 @@
             }
             if (newSubtype != oldSubtype) {
                 setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
-                if (mCurMethod != null) {
+                IInputMethod curMethod = getCurMethod();
+                if (curMethod != null) {
                     try {
                         updateSystemUiLocked(mImeWindowVis, mBackDisposition);
-                        mCurMethod.changeInputMethodSubtype(newSubtype);
+                        curMethod.changeInputMethodSubtype(newSubtype);
                     } catch (RemoteException e) {
                         Slog.w(TAG, "Failed to call changeInputMethodSubtype");
                     }
@@ -3068,7 +2949,7 @@
             // mCurMethodId should be updated after setSelectedInputMethodAndSubtypeLocked()
             // because mCurMethodId is stored as a history in
             // setSelectedInputMethodAndSubtypeLocked().
-            mCurMethodId = id;
+            setSelectedMethodId(id);
 
             if (LocalServices.getService(ActivityManagerInternal.class).isSystemReady()) {
                 Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
@@ -3162,35 +3043,37 @@
         }
 
         boolean res = false;
-        if (mCurMethod != null) {
-            if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken);
+        IInputMethod curMethod = getCurMethod();
+        if (curMethod != null) {
+            if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + getCurToken());
             // create a placeholder token for IMS so that IMS cannot inject windows into client app.
             Binder showInputToken = new Binder();
             mShowRequestWindowMap.put(showInputToken, windowToken);
-            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIIOOO(MSG_SHOW_SOFT_INPUT,
-                    getImeShowFlagsLocked(), reason, mCurMethod, resultReceiver, showInputToken));
+            executeOrSendMessage(curMethod, mCaller.obtainMessageIIOOO(MSG_SHOW_SOFT_INPUT,
+                    getImeShowFlagsLocked(), reason, curMethod, resultReceiver,
+                    showInputToken));
             mInputShown = true;
-            if (mHaveConnection && !mVisibleBound) {
-                bindCurrentInputMethodServiceLocked(
-                        mCurIntent, mVisibleConnection, IME_VISIBLE_BIND_FLAGS);
-                mVisibleBound = true;
+            if (hasConnection() && !isVisibleBound()) {
+                mBindingController.bindCurrentInputMethodServiceVisibleConnectionLocked();
             }
             res = true;
-        } else if (mHaveConnection && SystemClock.uptimeMillis()
-                >= (mLastBindTime+TIME_TO_RECONNECT)) {
-            // The client has asked to have the input method shown, but
-            // we have been sitting here too long with a connection to the
-            // service and no interface received, so let's disconnect/connect
-            // to try to prod things along.
-            EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId,
-                    SystemClock.uptimeMillis()-mLastBindTime,1);
-            Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
-            mContext.unbindService(this);
-            bindCurrentInputMethodServiceLocked(mCurIntent, this, mImeConnectionBindFlags);
         } else {
-            if (DEBUG) {
-                Slog.d(TAG, "Can't show input: connection = " + mHaveConnection + ", time = "
-                        + ((mLastBindTime+TIME_TO_RECONNECT) - SystemClock.uptimeMillis()));
+            long bindingDuration = SystemClock.uptimeMillis() - getLastBindTime();
+            if (hasConnection() && bindingDuration >= TIME_TO_RECONNECT) {
+                // The client has asked to have the input method shown, but
+                // we have been sitting here too long with a connection to the
+                // service and no interface received, so let's disconnect/connect
+                // to try to prod things along.
+                EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, getSelectedMethodId(),
+                        bindingDuration, 1);
+                Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
+                mBindingController.unbindMainConnectionLocked();
+                mBindingController.bindCurrentInputMethodServiceMainConnectionLocked();
+            } else {
+                if (DEBUG) {
+                    Slog.d(TAG, "Can't show input: connection = " + hasConnection() + ", time = "
+                            + (TIME_TO_RECONNECT - bindingDuration));
+                }
             }
         }
 
@@ -3261,7 +3144,8 @@
         // since Android Eclair.  That's why we need to accept IMM#hideSoftInput() even when only
         // IMMS#InputShown indicates that the software keyboard is shown.
         // TODO: Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested.
-        final boolean shouldHideSoftInput = (mCurMethod != null) && (mInputShown
+        IInputMethod curMethod = getCurMethod();
+        final boolean shouldHideSoftInput = (curMethod != null) && (mInputShown
                 || (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
         boolean res;
         if (shouldHideSoftInput) {
@@ -3271,15 +3155,14 @@
             // delivered to the IME process as an IPC.  Hence the inconsistency between
             // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
             // the final state.
-            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOOO(MSG_HIDE_SOFT_INPUT,
-                    reason, mCurMethod, resultReceiver, hideInputToken));
+            executeOrSendMessage(curMethod, mCaller.obtainMessageIOOO(MSG_HIDE_SOFT_INPUT,
+                    reason, curMethod, resultReceiver, hideInputToken));
             res = true;
         } else {
             res = false;
         }
-        if (mHaveConnection && mVisibleBound) {
-            mContext.unbindService(mVisibleConnection);
-            mVisibleBound = false;
+        if (hasConnection() && isVisibleBound()) {
+            mBindingController.unbindVisibleConnectionLocked();
         }
         mInputShown = false;
         mShowRequested = false;
@@ -3519,7 +3402,7 @@
                         // Note that we can trust client's display ID as long as it matches
                         // to the display ID obtained from the window.
                         if (cs.selfReportedDisplayId != mCurTokenDisplayId) {
-                            unbindCurrentMethodLocked();
+                            mBindingController.unbindCurrentMethodLocked();
                         }
                     }
                 } else if (isTextEditor && doAutoShow
@@ -3645,10 +3528,10 @@
         if (mCurFocusedWindowClient != null && client != null
                 && mCurFocusedWindowClient.client.asBinder() == client.asBinder()) {
             return true;
-        } else if (mCurIntent != null && InputMethodUtils.checkIfPackageBelongsToUid(
+        } else if (getCurIntent() != null && InputMethodUtils.checkIfPackageBelongsToUid(
                 mAppOpsManager,
                 uid,
-                mCurIntent.getComponent().getPackageName())) {
+                getCurIntent().getComponent().getPackageName())) {
             return true;
         }
         return false;
@@ -3734,7 +3617,7 @@
             if (!calledFromValidUserLocked()) {
                 return;
             }
-            executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
+            executeOrSendMessage(getCurMethod(), mCaller.obtainMessageO(
                     MSG_SHOW_IM_SUBTYPE_ENABLER, inputMethodId));
         }
     }
@@ -3755,7 +3638,7 @@
             String targetLastImiId = null;
             int subtypeId = NOT_A_SUBTYPE_ID;
             if (lastIme != null && lastImi != null) {
-                final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId);
+                final boolean imiIdIsSame = lastImi.getId().equals(getSelectedMethodId());
                 final int lastSubtypeHash = Integer.parseInt(lastIme.second);
                 final int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID
                         : mCurrentSubtype.hashCode();
@@ -3801,7 +3684,7 @@
             if (!TextUtils.isEmpty(targetLastImiId)) {
                 if (DEBUG) {
                     Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second
-                            + ", from: " + mCurMethodId + ", " + subtypeId);
+                            + ", from: " + getSelectedMethodId() + ", " + subtypeId);
                 }
                 setInputMethodWithSubtypeIdLocked(token, targetLastImiId, subtypeId);
                 return true;
@@ -3818,7 +3701,7 @@
                 return false;
             }
             final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
-                    onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
+                    onlyCurrentIme, mMethodMap.get(getSelectedMethodId()), mCurrentSubtype);
             if (nextSubtype == null) {
                 return false;
             }
@@ -3835,7 +3718,8 @@
                 return false;
             }
             final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
-                    false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype);
+                    false /* onlyCurrentIme */, mMethodMap.get(getSelectedMethodId()),
+                    mCurrentSubtype);
             if (nextSubtype == null) {
                 return false;
             }
@@ -4049,8 +3933,8 @@
     private void dumpDebug(ProtoOutputStream proto, long fieldId) {
         synchronized (mMethodMap) {
             final long token = proto.start(fieldId);
-            proto.write(CUR_METHOD_ID, mCurMethodId);
-            proto.write(CUR_SEQ, mCurSeq);
+            proto.write(CUR_METHOD_ID, getSelectedMethodId());
+            proto.write(CUR_SEQ, getSequenceNumber());
             proto.write(CUR_CLIENT, Objects.toString(mCurClient));
             proto.write(CUR_FOCUSED_WINDOW_NAME,
                     mWindowManagerInternal.getWindowName(mCurFocusedWindow));
@@ -4061,17 +3945,17 @@
             if (mCurAttribute != null) {
                 mCurAttribute.dumpDebug(proto, CUR_ATTRIBUTE);
             }
-            proto.write(CUR_ID, mCurId);
+            proto.write(CUR_ID, getCurId());
             proto.write(SHOW_REQUESTED, mShowRequested);
             proto.write(SHOW_EXPLICITLY_REQUESTED, mShowExplicitlyRequested);
             proto.write(SHOW_FORCED, mShowForced);
             proto.write(INPUT_SHOWN, mInputShown);
             proto.write(IN_FULLSCREEN_MODE, mInFullscreenMode);
-            proto.write(CUR_TOKEN, Objects.toString(mCurToken));
+            proto.write(CUR_TOKEN, Objects.toString(getCurToken()));
             proto.write(CUR_TOKEN_DISPLAY_ID, mCurTokenDisplayId);
             proto.write(SYSTEM_READY, mSystemReady);
             proto.write(LAST_SWITCH_USER_ID, mLastSwitchUserId);
-            proto.write(HAVE_CONNECTION, mHaveConnection);
+            proto.write(HAVE_CONNECTION, hasConnection());
             proto.write(BOUND_TO_METHOD, mBoundToMethod);
             proto.write(IS_INTERACTIVE, mIsInteractive);
             proto.write(BACK_DISPOSITION, mBackDisposition);
@@ -4089,14 +3973,14 @@
             Slog.d(TAG, "Got the notification of a user action.");
         }
         synchronized (mMethodMap) {
-            if (mCurToken != token) {
+            if (getCurToken() != token) {
                 if (DEBUG) {
                     Slog.d(TAG, "Ignoring the user action notification from IMEs that are no longer"
                             + " active.");
                 }
                 return;
             }
-            final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
+            final InputMethodInfo imi = mMethodMap.get(getSelectedMethodId());
             if (imi != null) {
                 mSwitchingController.onUserActionLocked(imi, mCurrentSubtype);
             }
@@ -4140,7 +4024,7 @@
                         "Using null token requires permission "
                         + android.Manifest.permission.WRITE_SECURE_SETTINGS);
             }
-        } else if (mCurToken != token) {
+        } else if (getCurToken() != token) {
             Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid()
                     + " token: " + token);
             return;
@@ -4512,7 +4396,7 @@
                 boolean reportToImeController = false;
                 try {
                     reportToImeController = mPlatformCompat.isChangeEnabledByUid(
-                            FINISH_INPUT_NO_FALLBACK_CONNECTION, mCurMethodUid);
+                            FINISH_INPUT_NO_FALLBACK_CONNECTION, getCurMethodUid());
                 } catch (RemoteException e) {
                 }
                 scheduleSetActiveToClient(mCurClient, mIsInteractive, mInFullscreenMode,
@@ -4802,7 +4686,7 @@
     @GuardedBy("mMethodMap")
     private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId,
             boolean setSubtypeOnly) {
-        mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
+        mSettings.saveCurrentInputMethodAndSubtypeToHistory(getSelectedMethodId(), mCurrentSubtype);
 
         // Set Subtype here
         if (imi == null || subtypeId < 0) {
@@ -4861,17 +4745,18 @@
 
     @GuardedBy("mMethodMap")
     InputMethodSubtype getCurrentInputMethodSubtypeLocked() {
-        if (mCurMethodId == null) {
+        String selectedMethodId = getSelectedMethodId();
+        if (selectedMethodId == null) {
             return null;
         }
         final boolean subtypeIsSelected = mSettings.isSubtypeSelected();
-        final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
+        final InputMethodInfo imi = mMethodMap.get(selectedMethodId);
         if (imi == null || imi.getSubtypeCount() == 0) {
             return null;
         }
         if (!subtypeIsSelected || mCurrentSubtype == null
                 || !InputMethodUtils.isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
-            int subtypeId = mSettings.getSelectedInputMethodSubtypeId(mCurMethodId);
+            int subtypeId = mSettings.getSelectedInputMethodSubtypeId(selectedMethodId);
             if (subtypeId == NOT_A_SUBTYPE_ID) {
                 // If there are no selected subtypes, the framework will try to find
                 // the most applicable subtype from explicitly or implicitly enabled
@@ -4901,7 +4786,7 @@
 
     @Nullable
     String getCurrentMethodId() {
-        return mCurMethodId;
+        return getSelectedMethodId();
     }
 
     private List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
@@ -5075,11 +4960,11 @@
 
         synchronized (mMethodMap) {
             final int uid = Binder.getCallingUid();
-            if (mCurMethodId == null) {
+            if (getSelectedMethodId() == null) {
                 return null;
             }
-            if (mCurToken != token) {
-                Slog.e(TAG, "Ignoring createInputContentUriToken mCurToken=" + mCurToken
+            if (getCurToken() != token) {
+                Slog.e(TAG, "Ignoring createInputContentUriToken mCurToken=" + getCurToken()
                         + " token=" + token);
                 return null;
             }
@@ -5214,23 +5099,23 @@
                 p.println("    sessionRequested=" + ci.sessionRequested);
                 p.println("    curSession=" + ci.curSession);
             }
-            p.println("  mCurMethodId=" + mCurMethodId);
+            p.println("  mCurMethodId=" + getSelectedMethodId());
             client = mCurClient;
-            p.println("  mCurClient=" + client + " mCurSeq=" + mCurSeq);
+            p.println("  mCurClient=" + client + " mCurSeq=" + getSequenceNumber());
             p.println("  mCurPerceptible=" + mCurPerceptible);
             p.println("  mCurFocusedWindow=" + mCurFocusedWindow
                     + " softInputMode=" +
                     InputMethodDebug.softInputModeToString(mCurFocusedWindowSoftInputMode)
                     + " client=" + mCurFocusedWindowClient);
             focusedWindowClient = mCurFocusedWindowClient;
-            p.println("  mCurId=" + mCurId + " mHaveConnection=" + mHaveConnection
-                    + " mBoundToMethod=" + mBoundToMethod + " mVisibleBound=" + mVisibleBound);
-            p.println("  mCurToken=" + mCurToken);
+            p.println("  mCurId=" + getCurId() + " mHaveConnection=" + hasConnection()
+                    + " mBoundToMethod=" + mBoundToMethod + " mVisibleBound=" + isVisibleBound());
+            p.println("  mCurToken=" + getCurToken());
             p.println("  mCurTokenDisplayId=" + mCurTokenDisplayId);
             p.println("  mCurHostInputToken=" + mCurHostInputToken);
-            p.println("  mCurIntent=" + mCurIntent);
-            method = mCurMethod;
-            p.println("  mCurMethod=" + mCurMethod);
+            p.println("  mCurIntent=" + getCurIntent());
+            method = getCurMethod();
+            p.println("  mCurMethod=" + getCurMethod());
             p.println("  mEnabledSession=" + mEnabledSession);
             p.println("  mShowRequested=" + mShowRequested
                     + " mShowExplicitlyRequested=" + mShowExplicitlyRequested
@@ -5736,7 +5621,7 @@
                 if (userId == mSettings.getCurrentUserId()) {
                     hideCurrentInputLocked(mCurFocusedWindow, 0, null,
                             SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND);
-                    unbindCurrentMethodLocked();
+                    mBindingController.unbindCurrentMethodLocked();
                     // Reset the current IME
                     resetSelectedInputMethodAndSubtypeLocked(null);
                     // Also reset the settings of the current IME
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index b8bb399..f70ad05 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -224,7 +224,7 @@
     public Context getSettingsContext(int displayId) {
         if (mSettingsContext == null || mSettingsContext.getDisplayId() != displayId) {
             final Context systemUiContext = ActivityThread.currentActivityThread()
-                    .createSystemUiContext(displayId);
+                    .getSystemUiContext(displayId);
             final Context windowContext = systemUiContext.createWindowContext(
                     WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG, null /* options */);
             mSettingsContext = new ContextThemeWrapper(
diff --git a/services/core/java/com/android/server/locales/LocaleManagerService.java b/services/core/java/com/android/server/locales/LocaleManagerService.java
index ffeaad1..457c2fd 100644
--- a/services/core/java/com/android/server/locales/LocaleManagerService.java
+++ b/services/core/java/com/android/server/locales/LocaleManagerService.java
@@ -154,10 +154,10 @@
         final ActivityTaskManagerInternal.PackageConfigurationUpdater updater =
                 mActivityTaskManagerInternal.createPackageConfigurationUpdater(appPackageName,
                         userId);
-        boolean isSuccess = updater.setLocales(locales).commit();
+        boolean isConfigChanged = updater.setLocales(locales).commit();
 
         //We want to send the broadcasts only if config was actually updated on commit.
-        if (isSuccess) {
+        if (isConfigChanged) {
             notifyAppWhoseLocaleChanged(appPackageName, userId, locales);
             notifyInstallerOfAppWhoseLocaleChanged(appPackageName, userId, locales);
             notifyRegisteredReceivers(appPackageName, userId, locales);
diff --git a/services/core/java/com/android/server/locales/LocaleManagerShellCommand.java b/services/core/java/com/android/server/locales/LocaleManagerShellCommand.java
index 769ea17..803b5a3 100644
--- a/services/core/java/com/android/server/locales/LocaleManagerShellCommand.java
+++ b/services/core/java/com/android/server/locales/LocaleManagerShellCommand.java
@@ -133,7 +133,7 @@
             try {
                 LocaleList locales = mBinderService.getApplicationLocales(packageName, userId);
                 getOutPrintWriter().println("Locales for " + packageName
-                        + " for user " + userId + " are " + locales);
+                        + " for user " + userId + " are [" + locales.toLanguageTags() + "]");
             } catch (RemoteException e) {
                 getOutPrintWriter().println("Remote Exception: " + e);
             } catch (IllegalArgumentException e) {
diff --git a/services/core/java/com/android/server/locales/TEST_MAPPING b/services/core/java/com/android/server/locales/TEST_MAPPING
index 097c2bc..27d2851 100644
--- a/services/core/java/com/android/server/locales/TEST_MAPPING
+++ b/services/core/java/com/android/server/locales/TEST_MAPPING
@@ -10,6 +10,9 @@
     },
     {
       "name": "CtsLocaleManagerTestCases"
+    },
+    {
+      "name": "CtsLocaleManagerHostTestCases"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index cd26fb5..2550e3a 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -39,6 +39,7 @@
 import android.Manifest.permission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.PendingIntent;
@@ -1239,6 +1240,32 @@
     }
 
     @Override
+    @RequiresPermission(android.Manifest.permission.AUTOMOTIVE_GNSS_CONTROLS)
+    public void setAutoGnssSuspended(boolean suspended) {
+        mContext.enforceCallingPermission(permission.AUTOMOTIVE_GNSS_CONTROLS, null);
+
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            throw new IllegalStateException(
+                    "setAutoGnssSuspended only allowed on automotive devices");
+        }
+
+        mGnssManagerService.setAutoGnssSuspended(suspended);
+    }
+
+    @Override
+    @RequiresPermission(android.Manifest.permission.AUTOMOTIVE_GNSS_CONTROLS)
+    public boolean isAutoGnssSuspended() {
+        mContext.enforceCallingPermission(permission.AUTOMOTIVE_GNSS_CONTROLS, null);
+
+        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+            throw new IllegalStateException(
+                    "isAutoGnssSuspended only allowed on automotive devices");
+        }
+
+        return mGnssManagerService.isAutoGnssSuspended();
+    }
+
+    @Override
     public boolean geocoderIsPresent() {
         return mGeocodeProvider != null;
     }
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
index b676f28..efd3037 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
@@ -30,6 +30,7 @@
 import android.compat.annotation.EnabledAfter;
 import android.content.Context;
 import android.content.Intent;
+import android.hardware.contexthub.HostEndpointInfo;
 import android.hardware.location.ContextHubInfo;
 import android.hardware.location.ContextHubManager;
 import android.hardware.location.ContextHubTransaction;
@@ -42,6 +43,7 @@
 import android.os.Build;
 import android.os.IBinder;
 import android.os.Looper;
+import android.os.Process;
 import android.os.RemoteException;
 import android.util.Log;
 import android.util.proto.ProtoOutputStream;
@@ -329,6 +331,15 @@
         mAppOpsManager = context.getSystemService(AppOpsManager.class);
 
         startMonitoringOpChanges();
+
+        HostEndpointInfo info = new HostEndpointInfo();
+        info.hostEndpointId = (char) mHostEndPointId;
+        info.packageName = mPackage;
+        info.attributionTag = mAttributionTag;
+        info.type = (mUid == Process.SYSTEM_UID)
+             ? HostEndpointInfo.Type.TYPE_FRAMEWORK
+             : HostEndpointInfo.Type.TYPE_APP;
+        mContextHubProxy.onHostEndpointConnected(info);
     }
 
     /* package */ ContextHubClientBroker(
@@ -862,6 +873,8 @@
             mRegistered = false;
         }
         mAppOpsManager.stopWatchingMode(this);
+
+        mContextHubProxy.onHostEndpointDisconnected(mHostEndPointId);
     }
 
     private String authStateToString(@ContextHubManager.AuthorizationState int state) {
diff --git a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
index 74630d1..9078f3f 100644
--- a/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
+++ b/services/core/java/com/android/server/location/contexthub/IContextHubWrapper.java
@@ -17,6 +17,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.hardware.contexthub.HostEndpointInfo;
 import android.hardware.contexthub.V1_0.ContextHub;
 import android.hardware.contexthub.V1_0.ContextHubMsg;
 import android.hardware.contexthub.V1_0.TransactionResult;
@@ -239,6 +240,20 @@
     public abstract void onMicrophoneSettingChanged(boolean enabled);
 
     /**
+     * Invoked whenever a host client connects with the framework.
+     *
+     * @param info The host endpoint info.
+     */
+    public void onHostEndpointConnected(HostEndpointInfo info) {}
+
+    /**
+     * Invoked whenever a host client disconnects from the framework.
+     *
+     * @param hostEndpointId The ID of the host endpoint that disconnected.
+     */
+    public void onHostEndpointDisconnected(short hostEndpointId) {}
+
+    /**
      * Sends a message to the Context Hub.
      *
      * @param hostEndpointId The host endpoint ID of the sender.
@@ -407,6 +422,24 @@
             onSettingChanged(android.hardware.contexthub.Setting.WIFI_SCANNING, enabled);
         }
 
+        @Override
+        public void onHostEndpointConnected(HostEndpointInfo info) {
+            try {
+                mHub.onHostEndpointConnected(info);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException in onHostEndpointConnected");
+            }
+        }
+
+        @Override
+        public void onHostEndpointDisconnected(short hostEndpointId) {
+            try {
+                mHub.onHostEndpointDisconnected((char) hostEndpointId);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException in onHostEndpointDisconnected");
+            }
+        }
+
         @ContextHubTransaction.Result
         public int sendMessageToContextHub(
                 short hostEndpointId, int contextHubId, NanoAppMessage message)
diff --git a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
index 7db234a..5fe7710 100644
--- a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
@@ -71,7 +71,8 @@
     private static final String CONFIG_GPS_LOCK = "GPS_LOCK";
     private static final String CONFIG_ES_EXTENSION_SEC = "ES_EXTENSION_SEC";
     public static final String CONFIG_NFW_PROXY_APPS = "NFW_PROXY_APPS";
-
+    public static final String CONFIG_ENABLE_PSDS_PERIODIC_DOWNLOAD =
+            "ENABLE_PSDS_PERIODIC_DOWNLOAD";
     // Limit on NI emergency mode time extension after emergency sessions ends
     private static final int MAX_EMERGENCY_MODE_EXTENSION_SECONDS = 300;  // 5 minute maximum
 
@@ -194,6 +195,13 @@
     }
 
     /**
+     * Returns true if PSDS periodic download is enabled, false otherwise.
+     */
+    boolean isPsdsPeriodicDownloadEnabled() {
+        return getBooleanConfig(CONFIG_ENABLE_PSDS_PERIODIC_DOWNLOAD, false);
+    }
+
+    /**
      * Updates the GNSS HAL satellite denylist.
      */
     void setSatelliteBlocklist(int[] constellations, int[] svids) {
@@ -374,6 +382,14 @@
         }
     }
 
+    private boolean getBooleanConfig(String configParameter, boolean defaultValue) {
+        String valueString = mProperties.getProperty(configParameter);
+        if (TextUtils.isEmpty(valueString)) {
+            return defaultValue;
+        }
+        return Boolean.parseBoolean(valueString);
+    }
+
     private static boolean isConfigEsExtensionSecSupported(
             HalInterfaceVersion gnssConfiguartionIfaceVersion) {
         // ES_EXTENSION_SEC is introduced in @2.0::IGnssConfiguration.hal
diff --git a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
index 7d0b98e..f114184 100644
--- a/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssLocationProvider.java
@@ -16,6 +16,8 @@
 
 package com.android.server.location.gnss;
 
+import static android.content.pm.PackageManager.FEATURE_WATCH;
+
 import static android.app.AlarmManager.ELAPSED_REALTIME_WAKEUP;
 import static android.location.provider.ProviderProperties.ACCURACY_FINE;
 import static android.location.provider.ProviderProperties.POWER_USAGE_HIGH;
@@ -55,6 +57,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.location.GnssCapabilities;
 import android.location.GnssStatus;
@@ -142,6 +145,9 @@
     private static final int AGPS_SUPL_MODE_MSA = 0x02;
     private static final int AGPS_SUPL_MODE_MSB = 0x01;
 
+    // PSDS stands for Predicted Satellite Data Service
+    private static final int DOWNLOAD_PSDS_DATA = 6;
+
     // TCP/IP constants.
     // Valid TCP/UDP port range is (0, 65535].
     private static final int TCP_MIN_PORT = 0;
@@ -243,6 +249,9 @@
     @GuardedBy("mLock")
     private boolean mBatchingEnabled;
 
+    @GuardedBy("mLock")
+    private boolean mAutomotiveSuspend;
+
     private boolean mShutdown;
     private boolean mStarted;
     private boolean mBatchingStarted;
@@ -648,6 +657,14 @@
                         mPsdsBackOff.reset();
                     }
                 });
+                PackageManager pm = mContext.getPackageManager();
+                if (pm != null && pm.hasSystemFeature(FEATURE_WATCH)
+                        && mGnssConfiguration.isPsdsPeriodicDownloadEnabled()) {
+                    if (DEBUG) Log.d(TAG, "scheduling next Psds download");
+                    mHandler.removeMessages(DOWNLOAD_PSDS_DATA);
+                    mHandler.sendEmptyMessageDelayed(DOWNLOAD_PSDS_DATA,
+                            GnssPsdsDownloader.PSDS_INTERVAL);
+                }
             } else {
                 // Try download PSDS data again later according to backoff time.
                 // Since this is delayed and not urgent, we do not hold a wake lock here.
@@ -721,6 +738,27 @@
         }
     }
 
+    /**
+     * Set whether the GnssLocationProvider is suspended. This method was added to help support
+     * power management use cases on automotive devices.
+     */
+    public void setAutoGnssSuspended(boolean suspended) {
+        synchronized (mLock) {
+            mAutomotiveSuspend = suspended;
+        }
+        mHandler.post(this::updateEnabled);
+    }
+
+    /**
+     * Return whether the GnssLocationProvider is suspended or not. This method was added to help
+     * support power management use cases on automotive devices.
+     */
+    public boolean isAutoGnssSuspended() {
+        synchronized (mLock) {
+            return mAutomotiveSuspend && !mGpsEnabled;
+        }
+    }
+
     private void handleEnable() {
         if (DEBUG) Log.d(TAG, "handleEnable");
 
@@ -776,6 +814,11 @@
                 && mProviderRequest.isActive()
                 && mProviderRequest.isBypass());
 
+        // .. disable if automotive device needs to go into suspend
+        synchronized (mLock) {
+            enabled &= !mAutomotiveSuspend;
+        }
+
         // ... and, finally, disable anyway, if device is being shut down
         enabled &= !mShutdown;
 
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index 5de9cf3..11fd727 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -109,6 +109,22 @@
         return mGnssLocationProvider;
     }
 
+    /**
+     * Set whether the GnssLocationProvider is suspended on the device. This method was added to
+     * help support power management use cases on automotive devices.
+     */
+    public void setAutoGnssSuspended(boolean suspended) {
+        mGnssLocationProvider.setAutoGnssSuspended(suspended);
+    }
+
+    /**
+     * Return whether the GnssLocationProvider is suspended or not. This method was added to
+     * help support power management use cases on automotive devices.
+     */
+    public boolean isAutoGnssSuspended() {
+        return mGnssLocationProvider.isAutoGnssSuspended();
+    }
+
     /** Retrieve the IGpsGeofenceHardware. */
     public IGpsGeofenceHardware getGnssGeofenceProxy() {
         return mGnssGeofenceProxy;
diff --git a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
index 8460d67..1781588 100644
--- a/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/gnss/GnssMeasurementsProvider.java
@@ -52,8 +52,6 @@
 
     private class GnssMeasurementListenerRegistration extends GnssListenerRegistration {
 
-        private static final String GNSS_MEASUREMENTS_BUCKET = "gnss_measurement";
-
         protected GnssMeasurementListenerRegistration(
                 @Nullable GnssMeasurementRequest request,
                 CallerIdentity callerIdentity,
@@ -70,15 +68,13 @@
         @Nullable
         @Override
         protected void onActive() {
-            mLocationAttributionHelper.reportHighPowerLocationStart(
-                    getIdentity(), GNSS_MEASUREMENTS_BUCKET, getKey());
+            mLocationAttributionHelper.reportHighPowerLocationStart(getIdentity());
         }
 
         @Nullable
         @Override
         protected void onInactive() {
-            mLocationAttributionHelper.reportHighPowerLocationStop(
-                    getIdentity(), GNSS_MEASUREMENTS_BUCKET, getKey());
+            mLocationAttributionHelper.reportHighPowerLocationStop(getIdentity());
         }
     }
 
diff --git a/services/core/java/com/android/server/location/gnss/GnssPsdsDownloader.java b/services/core/java/com/android/server/location/gnss/GnssPsdsDownloader.java
index 443a6c0a..dce9a12 100644
--- a/services/core/java/com/android/server/location/gnss/GnssPsdsDownloader.java
+++ b/services/core/java/com/android/server/location/gnss/GnssPsdsDownloader.java
@@ -38,6 +38,10 @@
  */
 class GnssPsdsDownloader {
 
+    // how often to request PSDS download, in milliseconds
+    // current setting 24 hours
+    static final long PSDS_INTERVAL = 24 * 60 * 60 * 1000;
+
     private static final String TAG = "GnssPsdsDownloader";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     private static final long MAXIMUM_CONTENT_LENGTH_BYTES = 1000000;  // 1MB.
diff --git a/services/core/java/com/android/server/location/gnss/gps_debug.conf b/services/core/java/com/android/server/location/gnss/gps_debug.conf
index 34ce96f..90daf8c 100644
--- a/services/core/java/com/android/server/location/gnss/gps_debug.conf
+++ b/services/core/java/com/android/server/location/gnss/gps_debug.conf
@@ -50,3 +50,12 @@
 # Set bit 0x2 if NI GPS functionalities are to be locked
 # default - non is locked for backward compatibility
 #GPS_LOCK = 0
+
+################################
+##### PSDS download settings #####
+################################
+# For wear devices only.
+# Enable periodic PSDS download once a day.
+# true: Enable periodic PSDS download
+# false: Disable periodic PSDS download
+#ENABLE_PSDS_PERIODIC_DOWNLOAD=false
diff --git a/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java b/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java
index 5cb360b..4838752 100644
--- a/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java
+++ b/services/core/java/com/android/server/location/injector/LocationAttributionHelper.java
@@ -24,55 +24,23 @@
 
 import android.location.util.identity.CallerIdentity;
 import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
 
 import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
 
 /**
  * Helps manage appop monitoring for multiple location clients.
  */
 public class LocationAttributionHelper {
 
-    private static class BucketKey {
-        private final String mBucket;
-        private final Object mKey;
-
-        private BucketKey(String bucket, Object key) {
-            mBucket = Objects.requireNonNull(bucket);
-            mKey = Objects.requireNonNull(key);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) {
-                return true;
-            }
-            if (o == null || getClass() != o.getClass()) {
-                return false;
-            }
-
-            BucketKey that = (BucketKey) o;
-            return mBucket.equals(that.mBucket)
-                    && mKey.equals(that.mKey);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(mBucket, mKey);
-        }
-    }
-
     private final AppOpsHelper mAppOpsHelper;
 
     @GuardedBy("this")
-    private final Map<CallerIdentity, Set<BucketKey>> mAttributions;
+    private final Map<CallerIdentity, Integer> mAttributions;
     @GuardedBy("this")
-    private final Map<CallerIdentity, Set<BucketKey>> mHighPowerAttributions;
+    private final Map<CallerIdentity, Integer> mHighPowerAttributions;
 
     public LocationAttributionHelper(AppOpsHelper appOpsHelper) {
         mAppOpsHelper = appOpsHelper;
@@ -84,15 +52,16 @@
     /**
      * Report normal location usage for the given caller in the given bucket, with a unique key.
      */
-    public synchronized void reportLocationStart(CallerIdentity identity, String bucket,
-            Object key) {
-        Set<BucketKey> keySet = mAttributions.computeIfAbsent(identity,
-                i -> new ArraySet<>());
-        boolean empty = keySet.isEmpty();
-        if (keySet.add(new BucketKey(bucket, key)) && empty) {
-            if (!mAppOpsHelper.startOpNoThrow(OP_MONITOR_LOCATION, identity)) {
-                mAttributions.remove(identity);
+    public synchronized void reportLocationStart(CallerIdentity identity) {
+        identity = CallerIdentity.forAggregation(identity);
+
+        int count = mAttributions.getOrDefault(identity, 0);
+        if (count == 0) {
+            if (mAppOpsHelper.startOpNoThrow(OP_MONITOR_LOCATION, identity)) {
+                mAttributions.put(identity, 1);
             }
+        } else {
+            mAttributions.put(identity, count + 1);
         }
     }
 
@@ -100,13 +69,15 @@
      * Report normal location usage has stopped for the given caller in the given bucket, with a
      * unique key.
      */
-    public synchronized void reportLocationStop(CallerIdentity identity, String bucket,
-            Object key) {
-        Set<BucketKey> keySet = mAttributions.get(identity);
-        if (keySet != null && keySet.remove(new BucketKey(bucket, key))
-                && keySet.isEmpty()) {
+    public synchronized void reportLocationStop(CallerIdentity identity) {
+        identity = CallerIdentity.forAggregation(identity);
+
+        int count = mAttributions.getOrDefault(identity, 0);
+        if (count == 1) {
             mAttributions.remove(identity);
             mAppOpsHelper.finishOp(OP_MONITOR_LOCATION, identity);
+        } else if (count > 1) {
+            mAttributions.put(identity, count - 1);
         }
     }
 
@@ -114,19 +85,19 @@
      * Report high power location usage for the given caller in the given bucket, with a unique
      * key.
      */
-    public synchronized void reportHighPowerLocationStart(CallerIdentity identity, String bucket,
-            Object key) {
-        Set<BucketKey> keySet = mHighPowerAttributions.computeIfAbsent(identity,
-                i -> new ArraySet<>());
-        boolean empty = keySet.isEmpty();
-        if (keySet.add(new BucketKey(bucket, key)) && empty) {
-            if (mAppOpsHelper.startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, identity)) {
-                if (D) {
-                    Log.v(TAG, "starting high power location attribution for " + identity);
-                }
-            } else {
-                mHighPowerAttributions.remove(identity);
+    public synchronized void reportHighPowerLocationStart(CallerIdentity identity) {
+        identity = CallerIdentity.forAggregation(identity);
+
+        int count = mHighPowerAttributions.getOrDefault(identity, 0);
+        if (count == 0) {
+            if (D) {
+                Log.v(TAG, "starting high power location attribution for " + identity);
             }
+            if (mAppOpsHelper.startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, identity)) {
+                mHighPowerAttributions.put(identity, 1);
+            }
+        } else {
+            mHighPowerAttributions.put(identity, count + 1);
         }
     }
 
@@ -134,16 +105,18 @@
      * Report high power location usage has stopped for the given caller in the given bucket,
      * with a unique key.
      */
-    public synchronized void reportHighPowerLocationStop(CallerIdentity identity, String bucket,
-            Object key) {
-        Set<BucketKey> keySet = mHighPowerAttributions.get(identity);
-        if (keySet != null && keySet.remove(new BucketKey(bucket, key))
-                && keySet.isEmpty()) {
+    public synchronized void reportHighPowerLocationStop(CallerIdentity identity) {
+        identity = CallerIdentity.forAggregation(identity);
+
+        int count = mHighPowerAttributions.getOrDefault(identity, 0);
+        if (count == 1) {
             if (D) {
                 Log.v(TAG, "stopping high power location attribution for " + identity);
             }
             mHighPowerAttributions.remove(identity);
             mAppOpsHelper.finishOp(OP_MONITOR_HIGH_POWER_LOCATION, identity);
+        } else if (count > 1) {
+            mHighPowerAttributions.put(identity, count - 1);
         }
     }
 }
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index cbca48c9..0ce24dd 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -398,7 +398,7 @@
             EVENT_LOG.logProviderClientActive(mName, getIdentity());
 
             if (!getRequest().isHiddenFromAppOps()) {
-                mLocationAttributionHelper.reportLocationStart(getIdentity(), getName(), getKey());
+                mLocationAttributionHelper.reportLocationStart(getIdentity());
             }
             onHighPowerUsageChanged();
 
@@ -413,7 +413,7 @@
 
             onHighPowerUsageChanged();
             if (!getRequest().isHiddenFromAppOps()) {
-                mLocationAttributionHelper.reportLocationStop(getIdentity(), getName(), getKey());
+                mLocationAttributionHelper.reportLocationStop(getIdentity());
             }
 
             onProviderListenerInactive();
@@ -488,10 +488,10 @@
                 if (!getRequest().isHiddenFromAppOps()) {
                     if (mIsUsingHighPower) {
                         mLocationAttributionHelper.reportHighPowerLocationStart(
-                                getIdentity(), getName(), getKey());
+                                getIdentity());
                     } else {
                         mLocationAttributionHelper.reportHighPowerLocationStop(
-                                getIdentity(), getName(), getKey());
+                                getIdentity());
                     }
                 }
             }
@@ -911,18 +911,21 @@
                 @Override
                 public void onPreExecute() {
                     mUseWakeLock = false;
-                    final int size = locationResult.size();
-                    for (int i = 0; i < size; ++i) {
-                        if (!locationResult.get(i).isMock()) {
-                            mUseWakeLock = true;
-                            break;
+
+                    // don't acquire a wakelock for passive requests or for mock locations
+                    if (getRequest().getIntervalMillis() != LocationRequest.PASSIVE_INTERVAL) {
+                        final int size = locationResult.size();
+                        for (int i = 0; i < size; ++i) {
+                            if (!locationResult.get(i).isMock()) {
+                                mUseWakeLock = true;
+                                break;
+                            }
                         }
                     }
 
                     // update last delivered location
                     setLastDeliveredLocation(locationResult.getLastLocation());
 
-                    // don't acquire a wakelock for mock locations to prevent abuse
                     if (mUseWakeLock) {
                         mWakeLock.acquire(WAKELOCK_TIMEOUT_MS);
                     }
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 14f5214..d4af681 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -101,6 +101,7 @@
 
     // State guarded by mLock.
     private final Object mLock = new Object();
+
     private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
     private final ArrayMap<IBinder, ClientRecord> mAllClientRecords = new ArrayMap<>();
     private int mCurrentUserId = -1;
@@ -351,9 +352,7 @@
 
         final long token = Binder.clearCallingIdentity();
         try {
-            synchronized (mLock) {
-                mAudioService.setBluetoothA2dpOn(on);
-            }
+            mAudioService.setBluetoothA2dpOn(on);
         } catch (RemoteException ex) {
             Slog.w(TAG, "RemoteException while calling setBluetoothA2dpOn. on=" + on);
         } finally {
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index e4ed0e5..4822d6a 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -291,35 +291,39 @@
                     asSystemService, useSuggested, previousFlagPlaySound);
         } else {
             if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
-                // Nothing to do, the volume cannot be changed
-                return;
-            }
-            if (direction == AudioManager.ADJUST_TOGGLE_MUTE
+                if (DEBUG) {
+                    Log.d(TAG, "Session does not support volume adjustment");
+                }
+            } else if (direction == AudioManager.ADJUST_TOGGLE_MUTE
                     || direction == AudioManager.ADJUST_MUTE
                     || direction == AudioManager.ADJUST_UNMUTE) {
                 Log.w(TAG, "Muting remote playback is not supported");
-                return;
-            }
-            if (DEBUG) {
-                Log.w(TAG, "adjusting volume, pkg=" + packageName + ", asSystemService="
-                        + asSystemService + ", dir=" + direction);
-            }
-            mSessionCb.adjustVolume(packageName, pid, uid, asSystemService, direction);
+            } else {
+                if (DEBUG) {
+                    Log.w(TAG, "adjusting volume, pkg=" + packageName + ", asSystemService="
+                            + asSystemService + ", dir=" + direction);
+                }
+                mSessionCb.adjustVolume(packageName, pid, uid, asSystemService, direction);
 
-            int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
-            mOptimisticVolume = volumeBefore + direction;
-            mOptimisticVolume = Math.max(0, Math.min(mOptimisticVolume, mMaxVolume));
-            mHandler.removeCallbacks(mClearOptimisticVolumeRunnable);
-            mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT);
-            if (volumeBefore != mOptimisticVolume) {
-                pushVolumeUpdate();
+                int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
+                mOptimisticVolume = volumeBefore + direction;
+                mOptimisticVolume = Math.max(0, Math.min(mOptimisticVolume, mMaxVolume));
+                mHandler.removeCallbacks(mClearOptimisticVolumeRunnable);
+                mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT);
+                if (volumeBefore != mOptimisticVolume) {
+                    pushVolumeUpdate();
+                }
+
+                if (DEBUG) {
+                    Log.d(TAG, "Adjusted optimistic volume to " + mOptimisticVolume + " max is "
+                            + mMaxVolume);
+                }
             }
+            // Always notify, even if the volume hasn't changed. This is important to ensure that
+            // System UI receives an event if a hardware volume key is pressed but the session that
+            // handles it does not allow volume adjustment. Without such an event, System UI would
+            // not show volume controls to the user.
             mService.notifyRemoteVolumeChanged(flags, this);
-
-            if (DEBUG) {
-                Log.d(TAG, "Adjusted optimistic volume to " + mOptimisticVolume + " max is "
-                        + mMaxVolume);
-            }
         }
     }
 
@@ -343,25 +347,28 @@
             });
         } else {
             if (mVolumeControlType != VolumeProvider.VOLUME_CONTROL_ABSOLUTE) {
-                // Nothing to do. The volume can't be set directly.
-                return;
-            }
-            value = Math.max(0, Math.min(value, mMaxVolume));
-            mSessionCb.setVolumeTo(packageName, pid, uid, value);
+                if (DEBUG) {
+                    Log.d(TAG, "Session does not support setting volume");
+                }
+            } else {
+                value = Math.max(0, Math.min(value, mMaxVolume));
+                mSessionCb.setVolumeTo(packageName, pid, uid, value);
 
-            int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
-            mOptimisticVolume = Math.max(0, Math.min(value, mMaxVolume));
-            mHandler.removeCallbacks(mClearOptimisticVolumeRunnable);
-            mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT);
-            if (volumeBefore != mOptimisticVolume) {
-                pushVolumeUpdate();
+                int volumeBefore = (mOptimisticVolume < 0 ? mCurrentVolume : mOptimisticVolume);
+                mOptimisticVolume = Math.max(0, Math.min(value, mMaxVolume));
+                mHandler.removeCallbacks(mClearOptimisticVolumeRunnable);
+                mHandler.postDelayed(mClearOptimisticVolumeRunnable, OPTIMISTIC_VOLUME_TIMEOUT);
+                if (volumeBefore != mOptimisticVolume) {
+                    pushVolumeUpdate();
+                }
+
+                if (DEBUG) {
+                    Log.d(TAG, "Set optimistic volume to " + mOptimisticVolume + " max is "
+                            + mMaxVolume);
+                }
             }
+            // Always notify, even if the volume hasn't changed.
             mService.notifyRemoteVolumeChanged(flags, this);
-
-            if (DEBUG) {
-                Log.d(TAG, "Set optimistic volume to " + mOptimisticVolume + " max is "
-                        + mMaxVolume);
-            }
         }
     }
 
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index df1eb6d..d17dbde 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -322,8 +322,11 @@
                                     gateway = InetAddresses.parseNumericAddress(in.readUTF());
                                 }
                                 // If the destination is a default IPv4 route, use the gateway
-                                // address unless already set.
-                                if (dest.getAddress() instanceof Inet4Address
+                                // address unless already set. If there is no destination, assume
+                                // it is default route and use the gateway address in all cases.
+                                if (dest == null) {
+                                    gatewayAddress = gateway;
+                                } else if (dest.getAddress() instanceof Inet4Address
                                         && dest.getPrefixLength() == 0 && gatewayAddress == null) {
                                     gatewayAddress = gateway;
                                 } else {
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 431b009..e6433db 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -159,7 +159,7 @@
     }
 
     public NetworkStatsFactory() {
-        this(new File("/proc/"), new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists());
+        this(new File("/proc/"), true);
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 097b071..c876d41 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -150,6 +150,7 @@
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FileRotator;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.net.module.util.BinderUtils;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
 
@@ -215,8 +216,6 @@
 
     private final PowerManager.WakeLock mWakeLock;
 
-    private final boolean mUseBpfTrafficStats;
-
     private final ContentObserver mContentObserver;
     private final ContentResolver mContentResolver;
 
@@ -438,7 +437,6 @@
         mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers");
         mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir");
         mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir");
-        mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists();
         mDeps = Objects.requireNonNull(deps, "missing Dependencies");
 
         final HandlerThread handlerThread = mDeps.makeHandlerThread();
@@ -1084,13 +1082,13 @@
         if (callingUid != android.os.Process.SYSTEM_UID && callingUid != uid) {
             return UNSUPPORTED;
         }
-        return nativeGetUidStat(uid, type, checkBpfStatsEnable());
+        return nativeGetUidStat(uid, type);
     }
 
     @Override
     public long getIfaceStats(@NonNull String iface, int type) {
         Objects.requireNonNull(iface);
-        long nativeIfaceStats = nativeGetIfaceStat(iface, type, checkBpfStatsEnable());
+        long nativeIfaceStats = nativeGetIfaceStat(iface, type);
         if (nativeIfaceStats == -1) {
             return nativeIfaceStats;
         } else {
@@ -1104,7 +1102,7 @@
 
     @Override
     public long getTotalStats(int type) {
-        long nativeTotalStats = nativeGetTotalStat(type, checkBpfStatsEnable());
+        long nativeTotalStats = nativeGetTotalStat(type);
         if (nativeTotalStats == -1) {
             return nativeTotalStats;
         } else {
@@ -1137,10 +1135,6 @@
         }
     }
 
-    private boolean checkBpfStatsEnable() {
-        return mUseBpfTrafficStats;
-    }
-
     /**
      * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
      * reflect current {@link #mPersistThreshold} value. Always defers to
@@ -2104,14 +2098,18 @@
 
         @Override
         public void notifyAlertReached() throws RemoteException {
-            mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */);
+            // This binder object can only have been obtained by a process that holds
+            // NETWORK_STATS_PROVIDER. Thus, no additional permission check is required.
+            BinderUtils.withCleanCallingIdentity(() ->
+                    mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */));
         }
 
         @Override
         public void notifyWarningOrLimitReached() {
             Log.d(TAG, mTag + ": notifyWarningOrLimitReached");
-            LocalServices.getService(NetworkPolicyManagerInternal.class)
-                    .onStatsProviderWarningOrLimitReached(mTag);
+            BinderUtils.withCleanCallingIdentity(() ->
+                    LocalServices.getService(NetworkPolicyManagerInternal.class)
+                            .onStatsProviderWarningOrLimitReached(mTag));
         }
 
         @Override
@@ -2249,7 +2247,7 @@
         }
     }
 
-    private static native long nativeGetTotalStat(int type, boolean useBpfStats);
-    private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats);
-    private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats);
+    private static native long nativeGetTotalStat(int type);
+    private static native long nativeGetIfaceStat(String iface, int type);
+    private static native long nativeGetUidStat(int uid, int type);
 }
diff --git a/services/core/java/com/android/server/net/OWNERS b/services/core/java/com/android/server/net/OWNERS
index a15fc3e..9c96d46f 100644
--- a/services/core/java/com/android/server/net/OWNERS
+++ b/services/core/java/com/android/server/net/OWNERS
@@ -1,6 +1,5 @@
 set noparent
-
-include platform/packages/modules/Connectivity:/OWNERS
+file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking
 
 jsharkey@android.com
 sudheersai@google.com
diff --git a/services/core/java/com/android/server/notification/BadgeExtractor.java b/services/core/java/com/android/server/notification/BadgeExtractor.java
index 70edfa1..642cbb3 100644
--- a/services/core/java/com/android/server/notification/BadgeExtractor.java
+++ b/services/core/java/com/android/server/notification/BadgeExtractor.java
@@ -69,11 +69,8 @@
 
         if (mConfig.isMediaNotificationFilteringEnabled()) {
             final Notification notif = record.getNotification();
-            if (notif.hasMediaSession()) {
-                if (notif.isStyle(Notification.DecoratedMediaCustomViewStyle.class)
-                        || notif.isStyle(Notification.MediaStyle.class)) {
-                    record.setShowBadge(false);
-                }
+            if (notif.isMediaNotification()) {
+                record.setShowBadge(false);
             }
         }
         return null;
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 7d31287..e6bc796 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -1065,7 +1065,7 @@
         }
     }
 
-    protected void setComponentState(ComponentName component, boolean enabled) {
+    protected void setComponentState(ComponentName component, int userId, boolean enabled) {
         boolean previous = !mSnoozingForCurrentProfiles.contains(component);
         if (previous == enabled) {
             return;
@@ -1082,20 +1082,15 @@
                 component.flattenToShortString());
 
         synchronized (mMutex) {
-            final IntArray userIds = mUserProfiles.getCurrentProfileIds();
-
-            for (int i = 0; i < userIds.size(); i++) {
-                final int userId = userIds.get(i);
-                if (enabled) {
-                    if (isPackageOrComponentAllowed(component.flattenToString(), userId)
-                            || isPackageOrComponentAllowed(component.getPackageName(), userId)) {
-                        registerServiceLocked(component, userId);
-                    } else {
-                        Slog.d(TAG, component + " no longer has permission to be bound");
-                    }
+            if (enabled) {
+                if (isPackageOrComponentAllowed(component.flattenToString(), userId)
+                        || isPackageOrComponentAllowed(component.getPackageName(), userId)) {
+                    registerServiceLocked(component, userId);
                 } else {
-                    unregisterServiceLocked(component, userId);
+                    Slog.d(TAG, component + " no longer has permission to be bound");
                 }
+            } else {
+                unregisterServiceLocked(component, userId);
             }
         }
     }
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 8aae6e0..583cdd5 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -179,7 +179,7 @@
     }
 
     private boolean isMediaNotification(NotificationRecord record) {
-        return record.getNotification().hasMediaSession();
+        return record.getNotification().isMediaNotification();
     }
 
     private boolean isCallCategory(NotificationRecord record) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index cc965d3..99fdb2d 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -151,6 +151,7 @@
 import android.app.NotificationManager;
 import android.app.NotificationManager.Policy;
 import android.app.PendingIntent;
+import android.app.RemoteServiceException.BadForegroundServiceNotificationException;
 import android.app.StatsManager;
 import android.app.StatusBarManager;
 import android.app.UriGrantsManager;
@@ -1265,10 +1266,11 @@
                 // Still crash for foreground services, preventing the not-crash behaviour abused
                 // by apps to give us a garbage notification and silently start a fg service.
                 Binder.withCleanCallingIdentity(
-                        () -> mAm.crashApplication(uid, initialPid, pkg, -1,
+                        () -> mAm.crashApplicationWithType(uid, initialPid, pkg, -1,
                             "Bad notification(tag=" + tag + ", id=" + id + ") posted from package "
                                 + pkg + ", crashing app(uid=" + uid + ", pid=" + initialPid + "): "
-                                + message, true /* force */));
+                                + message, true /* force */,
+                                BadForegroundServiceNotificationException.TYPE_ID));
             }
         }
 
@@ -4456,13 +4458,14 @@
         @Override
         public void requestBindListener(ComponentName component) {
             checkCallerIsSystemOrSameApp(component.getPackageName());
+            int uid = Binder.getCallingUid();
             final long identity = Binder.clearCallingIdentity();
             try {
                 ManagedServices manager =
                         mAssistants.isComponentEnabledForCurrentProfiles(component)
                         ? mAssistants
                         : mListeners;
-                manager.setComponentState(component, true);
+                manager.setComponentState(component, UserHandle.getUserId(uid), true);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -4470,12 +4473,14 @@
 
         @Override
         public void requestUnbindListener(INotificationListener token) {
+            int uid = Binder.getCallingUid();
             final long identity = Binder.clearCallingIdentity();
             try {
                 // allow bound services to disable themselves
                 synchronized (mNotificationLock) {
                     final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
-                    info.getOwner().setComponentState(info.component, false);
+                    info.getOwner().setComponentState(
+                            info.component, UserHandle.getUserId(uid), false);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -4967,11 +4972,12 @@
 
         @Override
         public void requestUnbindProvider(IConditionProvider provider) {
+            int uid = Binder.getCallingUid();
             final long identity = Binder.clearCallingIdentity();
             try {
                 // allow bound services to disable themselves
                 final ManagedServiceInfo info = mConditionProviders.checkServiceToken(provider);
-                info.getOwner().setComponentState(info.component, false);
+                info.getOwner().setComponentState(info.component, UserHandle.getUserId(uid), false);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -4980,9 +4986,10 @@
         @Override
         public void requestBindProvider(ComponentName component) {
             checkCallerIsSystemOrSameApp(component.getPackageName());
+            int uid = Binder.getCallingUid();
             final long identity = Binder.clearCallingIdentity();
             try {
-                mConditionProviders.setComponentState(component, true);
+                mConditionProviders.setComponentState(component, UserHandle.getUserId(uid), true);
             } finally {
                 Binder.restoreCallingIdentity(identity);
             }
@@ -6815,13 +6822,11 @@
 
 
         // blocked apps
-        boolean isMediaNotification = n.isMediaNotification()
-                && n.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) != null;
         boolean isBlocked = !areNotificationsEnabledForPackageInt(pkg, uid);
         synchronized (mNotificationLock) {
             isBlocked |= isRecordBlockedLocked(r);
         }
-        if (isBlocked && !isMediaNotification) {
+        if (isBlocked && !n.isMediaNotification()) {
             if (DBG) {
                 Slog.e(TAG, "Suppressing notification from package " + r.getSbn().getPackageName()
                         + " by user request.");
@@ -7210,10 +7215,8 @@
                     final StatusBarNotification n = r.getSbn();
                     final Notification notification = n.getNotification();
 
-                    boolean isMediaNotification = notification.isMediaNotification()
-                            && notification.extras.getParcelable(
-                                    Notification.EXTRA_MEDIA_SESSION) != null;
-                    if (!isMediaNotification && (appBanned || isRecordBlockedLocked(r))) {
+                    if (!notification.isMediaNotification()
+                            && (appBanned || isRecordBlockedLocked(r))) {
                         mUsageStats.registerBlocked(r);
                         if (DBG) {
                             Slog.e(TAG, "Suppressing notification from package " + pkg);
@@ -7240,7 +7243,9 @@
                     if (index < 0) {
                         mNotificationList.add(r);
                         mUsageStats.registerPostedByApp(r);
-                        r.setInterruptive(isVisuallyInterruptive(null, r));
+                        final boolean isInterruptive = isVisuallyInterruptive(null, r);
+                        r.setInterruptive(isInterruptive);
+                        r.setTextChanged(isInterruptive);
                     } else {
                         old = mNotificationList.get(index);  // Potentially *changes* old
                         mNotificationList.set(index, r);
@@ -9634,7 +9639,7 @@
         }
         final long identity = Binder.clearCallingIdentity();
         try {
-            List<String> associations = mCompanionManager.getAssociations(
+            List<?> associations = mCompanionManager.getAssociations(
                     info.component.getPackageName(), info.userid);
             if (!ArrayUtils.isEmpty(associations)) {
                 return true;
diff --git a/services/core/java/com/android/server/notification/VibratorHelper.java b/services/core/java/com/android/server/notification/VibratorHelper.java
index 0a69aec..be5f219 100644
--- a/services/core/java/com/android/server/notification/VibratorHelper.java
+++ b/services/core/java/com/android/server/notification/VibratorHelper.java
@@ -89,7 +89,7 @@
      */
     public void vibrate(VibrationEffect effect, AudioAttributes attrs, String reason) {
         mVibrator.vibrate(Process.SYSTEM_UID, PackageManagerService.PLATFORM_PACKAGE_NAME,
-                effect, reason, attrs);
+                effect, reason, new VibrationAttributes.Builder(attrs).build());
     }
 
     /** Stop all notification vibrations (ringtone, alarm, notification usages). */
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 53c2802..6f54625 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -500,16 +500,10 @@
                 forcedQueryablePackageNames[i] = forcedQueryablePackageNames[i].intern();
             }
         }
-        final StateProvider stateProvider = new StateProvider() {
-            // TODO: This lock and its handling should be owned by AppsFilter
-            private final Object mLock = new Object();
-
-            @Override
-            public void runWithState(CurrentStateCallback command) {
-                synchronized (mLock) {
-                    command.currentState(pms.getPackageStates(),
-                            injector.getUserManagerInternal().getUserInfos());
-                }
+        final StateProvider stateProvider = command -> {
+            synchronized (injector.getLock()) {
+                command.currentState(injector.getSettings().getPackagesLocked().untrackedStorage(),
+                        injector.getUserManagerInternal().getUserInfos());
             }
         };
         AppsFilter appsFilter = new AppsFilter(stateProvider, featureConfig,
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index af9c401..27db2f9 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -121,6 +121,8 @@
 
     private final Injector mInjector;
 
+    private final DexOptHelper mDexOptHelper;
+
     private final Object mLock = new Object();
 
     // Thread currently running dexopt. This will be null if dexopt is not running.
@@ -168,13 +170,15 @@
         void onPackagesUpdated(ArraySet<String> updatedPackages);
     }
 
-    public BackgroundDexOptService(Context context, DexManager dexManager) {
-        this(new Injector(context, dexManager));
+    public BackgroundDexOptService(Context context, DexManager dexManager,
+            PackageManagerService pm) {
+        this(new Injector(context, dexManager, pm));
     }
 
     @VisibleForTesting
     public BackgroundDexOptService(Injector injector) {
         mInjector = injector;
+        mDexOptHelper = mInjector.getDexOptHelper();
         LocalServices.addService(BackgroundDexOptService.class, this);
         mDowngradeUnusedAppsThresholdInMillis = mInjector.getDowngradeUnusedAppsThresholdInMillis();
     }
@@ -251,15 +255,13 @@
                 resetStatesForNewDexOptRunLocked(Thread.currentThread());
             }
             PackageManagerService pm = mInjector.getPackageManagerService();
-            DexOptHelper dexOptHelper = new DexOptHelper(pm);
             ArraySet<String> packagesToOptimize;
             if (packageNames == null) {
-                packagesToOptimize = dexOptHelper.getOptimizablePackages();
+                packagesToOptimize = mDexOptHelper.getOptimizablePackages();
             } else {
                 packagesToOptimize = new ArraySet<>(packageNames);
             }
-            return runIdleOptimization(pm, dexOptHelper, packagesToOptimize,
-                    /* isPostBootUpdate= */ false);
+            return runIdleOptimization(pm, packagesToOptimize, /* isPostBootUpdate= */ false);
         } finally {
             Binder.restoreCallingIdentity(identity);
             markDexOptCompleted();
@@ -320,8 +322,7 @@
             return false;
         }
 
-        DexOptHelper dexOptHelper = new DexOptHelper(pm);
-        ArraySet<String> pkgs = dexOptHelper.getOptimizablePackages();
+        ArraySet<String> pkgs = mDexOptHelper.getOptimizablePackages();
         if (pkgs.isEmpty()) {
             Slog.i(TAG, "No packages to optimize");
             markPostBootUpdateCompleted(params);
@@ -347,7 +348,7 @@
                         tr.traceBegin("jobExecution");
                         boolean completed = false;
                         try {
-                            completed = runIdleOptimization(pm, dexOptHelper, pkgs,
+                            completed = runIdleOptimization(pm, pkgs,
                                     params.getJobId() == JOB_POST_BOOT_UPDATE);
                         } finally { // Those cleanup should be done always.
                             tr.traceEnd();
@@ -461,7 +462,7 @@
     @GuardedBy("mLock")
     private void controlDexOptBlockingLocked(boolean block) {
         PackageManagerService pm = mInjector.getPackageManagerService();
-        new DexOptHelper(pm).controlDexOptBlocking(block);
+        mDexOptHelper.controlDexOptBlocking(block);
     }
 
     private void scheduleAJob(int jobId) {
@@ -511,10 +512,10 @@
     }
 
     /** Returns true if completed */
-    private boolean runIdleOptimization(PackageManagerService pm, DexOptHelper dexOptHelper,
-            ArraySet<String> pkgs, boolean isPostBootUpdate) {
+    private boolean runIdleOptimization(PackageManagerService pm, ArraySet<String> pkgs,
+            boolean isPostBootUpdate) {
         long lowStorageThreshold = getLowStorageThreshold();
-        int status = idleOptimizePackages(pm, dexOptHelper, pkgs, lowStorageThreshold,
+        int status = idleOptimizePackages(pm, pkgs, lowStorageThreshold,
                 isPostBootUpdate);
         logStatus(status);
         synchronized (mLock) {
@@ -562,8 +563,8 @@
     }
 
     @Status
-    private int idleOptimizePackages(PackageManagerService pm, DexOptHelper dexOptHelper,
-            ArraySet<String> pkgs, long lowStorageThreshold, boolean isPostBootUpdate) {
+    private int idleOptimizePackages(PackageManagerService pm, ArraySet<String> pkgs,
+            long lowStorageThreshold, boolean isPostBootUpdate) {
         ArraySet<String> updatedPackages = new ArraySet<>();
         ArraySet<String> updatedPackagesDueToSecondaryDex = new ArraySet<>();
 
@@ -600,7 +601,7 @@
                             // Should be aborted by the scheduler.
                             return abortCode;
                         }
-                        @DexOptResult int downgradeResult = downgradePackage(pm, dexOptHelper, pkg,
+                        @DexOptResult int downgradeResult = downgradePackage(pm, pkg,
                                 /* isForPrimaryDex= */ true, isPostBootUpdate);
                         if (downgradeResult == PackageDexOptimizer.DEX_OPT_PERFORMED) {
                             updatedPackages.add(pkg);
@@ -611,7 +612,7 @@
                             return status;
                         }
                         if (supportSecondaryDex) {
-                            downgradeResult = downgradePackage(pm, dexOptHelper, pkg,
+                            downgradeResult = downgradePackage(pm, pkg,
                                     /* isForPrimaryDex= */false, isPostBootUpdate);
                             status = convertPackageDexOptimizerStatusToInternal(downgradeResult);
                             if (status != STATUS_OK) {
@@ -625,9 +626,8 @@
                 }
             }
 
-            @Status int primaryResult = optimizePackages(dexOptHelper, pkgs,
-                    lowStorageThreshold, /*isForPrimaryDex=*/ true, updatedPackages,
-                    isPostBootUpdate);
+            @Status int primaryResult = optimizePackages(pkgs, lowStorageThreshold,
+                    /*isForPrimaryDex=*/ true, updatedPackages, isPostBootUpdate);
             if (primaryResult != STATUS_OK) {
                 return primaryResult;
             }
@@ -636,9 +636,9 @@
                 return STATUS_OK;
             }
 
-            @Status int secondaryResult = optimizePackages(dexOptHelper, pkgs,
-                    lowStorageThreshold, /*isForPrimaryDex*/ false,
-                    updatedPackagesDueToSecondaryDex, isPostBootUpdate);
+            @Status int secondaryResult = optimizePackages(pkgs, lowStorageThreshold,
+                    /*isForPrimaryDex*/ false, updatedPackagesDueToSecondaryDex,
+                    isPostBootUpdate);
             return secondaryResult;
         } finally {
             // Always let the pinner service know about changes.
@@ -651,9 +651,8 @@
     }
 
     @Status
-    private int optimizePackages(DexOptHelper dexOptHelper,
-            ArraySet<String> pkgs, long lowStorageThreshold, boolean isForPrimaryDex,
-            ArraySet<String> updatedPackages, boolean isPostBootUpdate) {
+    private int optimizePackages(ArraySet<String> pkgs, long lowStorageThreshold,
+            boolean isForPrimaryDex, ArraySet<String> updatedPackages, boolean isPostBootUpdate) {
         for (String pkg : pkgs) {
             int abortCode = abortIdleOptimizations(lowStorageThreshold);
             if (abortCode != STATUS_OK) {
@@ -661,8 +660,7 @@
                 return abortCode;
             }
 
-            @DexOptResult int result = optimizePackage(dexOptHelper, pkg, isForPrimaryDex,
-                    isPostBootUpdate);
+            @DexOptResult int result = optimizePackage(pkg, isForPrimaryDex, isPostBootUpdate);
             if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) {
                 updatedPackages.add(pkg);
             } else if (result != PackageDexOptimizer.DEX_OPT_SKIPPED) {
@@ -681,8 +679,8 @@
      * @return PackageDexOptimizer.DEX_*
      */
     @DexOptResult
-    private int downgradePackage(PackageManagerService pm, DexOptHelper dexOptHelper, String pkg,
-            boolean isForPrimaryDex, boolean isPostBootUpdate) {
+    private int downgradePackage(PackageManagerService pm, String pkg, boolean isForPrimaryDex,
+            boolean isPostBootUpdate) {
         if (DEBUG) {
             Slog.d(TAG, "Downgrading " + pkg);
         }
@@ -704,10 +702,10 @@
                 // remove their compiler artifacts from dalvik cache.
                 pm.deleteOatArtifactsOfPackage(pkg);
             } else {
-                result = performDexOptPrimary(dexOptHelper, pkg, reason, dexoptFlags);
+                result = performDexOptPrimary(pkg, reason, dexoptFlags);
             }
         } else {
-            result = performDexOptSecondary(dexOptHelper, pkg, reason, dexoptFlags);
+            result = performDexOptSecondary(pkg, reason, dexoptFlags);
         }
 
         if (result == PackageDexOptimizer.DEX_OPT_PERFORMED) {
@@ -733,15 +731,13 @@
      *
      * Optimize package if needed. Note that there can be no race between
      * concurrent jobs because PackageDexOptimizer.performDexOpt is synchronized.
-     * @param dexOptHelper An instance of DexOptHelper
      * @param pkg The package to be downgraded.
      * @param isForPrimaryDex Apps can have several dex file, primary and secondary.
      * @param isPostBootUpdate is post boot update or not.
      * @return PackageDexOptimizer#DEX_OPT_*
      */
     @DexOptResult
-    private int optimizePackage(DexOptHelper dexOptHelper, String pkg,
-            boolean isForPrimaryDex, boolean isPostBootUpdate) {
+    private int optimizePackage(String pkg, boolean isForPrimaryDex, boolean isPostBootUpdate) {
         int reason = isPostBootUpdate ? PackageManagerService.REASON_POST_BOOT
                 : PackageManagerService.REASON_BACKGROUND_DEXOPT;
         int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE;
@@ -753,27 +749,27 @@
         // System server share the same code path as primary dex files.
         // PackageManagerService will select the right optimization path for it.
         if (isForPrimaryDex || PLATFORM_PACKAGE_NAME.equals(pkg)) {
-            return performDexOptPrimary(dexOptHelper, pkg, reason, dexoptFlags);
+            return performDexOptPrimary(pkg, reason, dexoptFlags);
         } else {
-            return performDexOptSecondary(dexOptHelper, pkg, reason, dexoptFlags);
+            return performDexOptSecondary(pkg, reason, dexoptFlags);
         }
     }
 
     @DexOptResult
-    private int performDexOptPrimary(DexOptHelper dexOptHelper, String pkg, int reason,
+    private int performDexOptPrimary(String pkg, int reason,
             int dexoptFlags) {
         return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/ true,
-                () -> dexOptHelper.performDexOptWithStatus(
+                () -> mDexOptHelper.performDexOptWithStatus(
                         new DexoptOptions(pkg, reason, dexoptFlags)));
     }
 
     @DexOptResult
-    private int performDexOptSecondary(DexOptHelper dexOptHelper, String pkg, int reason,
+    private int performDexOptSecondary(String pkg, int reason,
             int dexoptFlags) {
         DexoptOptions dexoptOptions = new DexoptOptions(pkg, reason,
                 dexoptFlags | DexoptOptions.DEXOPT_ONLY_SECONDARY_DEX);
         return trackPerformDexOpt(pkg, /*isForPrimaryDex=*/ false,
-                () -> dexOptHelper.performDexOpt(dexoptOptions)
+                () -> mDexOptHelper.performDexOpt(dexoptOptions)
                     ? PackageDexOptimizer.DEX_OPT_PERFORMED : PackageDexOptimizer.DEX_OPT_FAILED
         );
     }
@@ -911,11 +907,13 @@
     static final class Injector {
         private final Context mContext;
         private final DexManager mDexManager;
+        private final PackageManagerService mPackageManagerService;
         private final File mDataDir = Environment.getDataDirectory();
 
-        Injector(Context context, DexManager dexManager) {
+        Injector(Context context, DexManager dexManager, PackageManagerService pm) {
             mContext = context;
             mDexManager = dexManager;
+            mPackageManagerService = pm;
         }
 
         Context getContext() {
@@ -923,7 +921,11 @@
         }
 
         PackageManagerService getPackageManagerService() {
-            return (PackageManagerService) ServiceManager.getService("package");
+            return mPackageManagerService;
+        }
+
+        DexOptHelper getDexOptHelper() {
+            return new DexOptHelper(getPackageManagerService());
         }
 
         JobScheduler getJobScheduler() {
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index 73322d0..3e849f8 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -517,6 +517,11 @@
     int getComponentEnabledSetting(@NonNull ComponentName component, int callingUid,
             @UserIdInt int userId);
 
+    @Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
+    @PackageManager.EnabledState
+    int getComponentEnabledSettingInternal(@NonNull ComponentName component, int callingUid,
+            @UserIdInt int userId);
+
     /**
      * @return true if the runtime app user enabled state, runtime component user enabled state,
      * install-time app manifest enabled state, and install-time component manifest enabled state
@@ -616,6 +621,10 @@
     @Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
     int getUidTargetSdkVersion(int uid);
 
+    /**
+     * @see PackageManagerInternal#getProcessesForUid(int)
+     */
+    @Computer.LiveImplementation(override = LiveImplementation.MANDATORY)
     @Nullable
     ArrayMap<String, ProcessInfo> getProcessesForUid(int uid);
     // End block
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 15f4541..2d61773 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -5026,20 +5026,26 @@
             @UserIdInt int userId) {
         enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
                 false /*checkShell*/, "getComponentEnabled");
+        return getComponentEnabledSettingInternal(component, callingUid, userId);
+    }
 
+    @PackageManager.EnabledState
+    @Override
+    public int getComponentEnabledSettingInternal(@NonNull ComponentName component, int callingUid,
+            @UserIdInt int userId) {
         if (component == null) return COMPONENT_ENABLED_STATE_DEFAULT;
         if (!mUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED;
 
-            try {
-                if (shouldFilterApplication(
-                        mSettings.getPackage(component.getPackageName()), callingUid,
-                        component, TYPE_UNKNOWN, userId)) {
-                    throw new PackageManager.NameNotFoundException(component.getPackageName());
-                }
-                return mSettings.getComponentEnabledSetting(component, userId);
-            } catch (PackageManager.NameNotFoundException e) {
-                throw new IllegalArgumentException("Unknown component: " + component);
+        try {
+            if (shouldFilterApplication(
+                    mSettings.getPackage(component.getPackageName()), callingUid,
+                    component, TYPE_UNKNOWN, userId)) {
+                throw new PackageManager.NameNotFoundException(component.getPackageName());
             }
+            return mSettings.getComponentEnabledSetting(component, userId);
+        } catch (PackageManager.NameNotFoundException e) {
+            throw new IllegalArgumentException("Unknown component: " + component);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/ComputerLocked.java b/services/core/java/com/android/server/pm/ComputerLocked.java
index 2d65b16..f180d19 100644
--- a/services/core/java/com/android/server/pm/ComputerLocked.java
+++ b/services/core/java/com/android/server/pm/ComputerLocked.java
@@ -655,6 +655,14 @@
     }
 
     @Override
+    public int getComponentEnabledSettingInternal(@NonNull ComponentName component, int callingUid,
+            @UserIdInt int userId) {
+        synchronized (mLock) {
+            return super.getComponentEnabledSettingInternal(component, callingUid, userId);
+        }
+    }
+
+    @Override
     public boolean isComponentEffectivelyEnabled(@NonNull ComponentInfo componentInfo,
             @UserIdInt int userId) {
         synchronized (mLock) {
diff --git a/services/core/java/com/android/server/pm/ComputerTracker.java b/services/core/java/com/android/server/pm/ComputerTracker.java
index ddefe01..a3cd092 100644
--- a/services/core/java/com/android/server/pm/ComputerTracker.java
+++ b/services/core/java/com/android/server/pm/ComputerTracker.java
@@ -1101,6 +1101,15 @@
     }
 
     @Override
+    public int getComponentEnabledSettingInternal(@NonNull ComponentName component, int callingUid,
+            @UserIdInt int userId) {
+        try (ThreadComputer current = snapshot()) {
+            return current.mComputer.getComponentEnabledSettingInternal(
+                    component, callingUid, userId);
+        }
+    }
+
+    @Override
     public boolean isComponentEffectivelyEnabled(@NonNull ComponentInfo componentInfo,
             @UserIdInt int userId) {
         try (ThreadComputer current = snapshot()) {
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 39ed9c2..5ca0618 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -649,12 +649,17 @@
             mPm.checkPackageFrozen(pkgName);
         }
 
-        // Also need to kill any apps that are dependent on the library.
+        final boolean isReplace =
+                reconciledPkg.mPrepareResult != null && reconciledPkg.mPrepareResult.mReplace;
+        // Also need to kill any apps that are dependent on the library, except the case of
+        // installation of new version static shared library.
         if (clientLibPkgs != null) {
-            for (int i = 0; i < clientLibPkgs.size(); i++) {
-                AndroidPackage clientPkg = clientLibPkgs.get(i);
-                mPm.killApplication(clientPkg.getPackageName(),
-                        clientPkg.getUid(), "update lib");
+            if (pkg.getStaticSharedLibName() == null || isReplace) {
+                for (int i = 0; i < clientLibPkgs.size(); i++) {
+                    AndroidPackage clientPkg = clientLibPkgs.get(i);
+                    mPm.killApplication(clientPkg.getPackageName(),
+                            clientPkg.getUid(), "update lib");
+                }
             }
         }
 
@@ -676,8 +681,6 @@
             ksms.addScannedPackageLPw(pkg);
 
             mPm.mComponentResolver.addAllComponents(pkg, chatty);
-            final boolean isReplace =
-                    reconciledPkg.mPrepareResult != null && reconciledPkg.mPrepareResult.mReplace;
             mPm.mAppsFilter.addPackage(pkgSetting, isReplace);
             mPm.addAllPackageProperties(pkg);
 
@@ -2050,6 +2053,7 @@
             }
         }
 
+        final String packageName = pkg.getPackageName();
         for (Map.Entry<String, String> entry : fsverityCandidates.entrySet()) {
             final String filePath = entry.getKey();
             final String signaturePath = entry.getValue();
@@ -2077,10 +2081,13 @@
                     try {
                         // A file may already have fs-verity, e.g. when reused during a split
                         // install. If the measurement succeeds, no need to attempt to set up.
-                        mPm.mInstaller.assertFsverityRootHashMatches(filePath, rootHash);
+                        mPm.mInstaller.assertFsverityRootHashMatches(packageName, filePath,
+                                rootHash);
                     } catch (Installer.InstallerException e) {
-                        mPm.mInstaller.installApkVerity(filePath, fd, result.getContentSize());
-                        mPm.mInstaller.assertFsverityRootHashMatches(filePath, rootHash);
+                        mPm.mInstaller.installApkVerity(packageName, filePath, fd,
+                                result.getContentSize());
+                        mPm.mInstaller.assertFsverityRootHashMatches(packageName, filePath,
+                                rootHash);
                     }
                 } finally {
                     IoUtils.closeQuietly(fd);
@@ -2349,10 +2356,9 @@
                 // Set install reason for users that are having the package newly installed.
                 final int[] allUsersList = mPm.mUserManager.getUserIds();
                 if (userId == UserHandle.USER_ALL) {
-                    // TODO(b/152629990): It appears that the package doesn't actually get newly
-                    //  installed in this case, so the installReason shouldn't get modified?
                     for (int currentUserId : allUsersList) {
-                        if (!previousUserIds.contains(currentUserId)) {
+                        if (!previousUserIds.contains(currentUserId)
+                                && ps.getInstalled(currentUserId)) {
                             ps.setInstallReason(installReason, currentUserId);
                         }
                     }
@@ -3126,10 +3132,12 @@
                             true, true, pkgList, uidArray, null);
                 }
             } else if (!ArrayUtils.isEmpty(res.mLibraryConsumers)) { // if static shared lib
+                // No need to kill consumers if it's installation of new version static shared lib.
+                final boolean dontKillApp = !update && res.mPkg.getStaticSharedLibName() != null;
                 for (int i = 0; i < res.mLibraryConsumers.size(); i++) {
                     AndroidPackage pkg = res.mLibraryConsumers.get(i);
                     // send broadcast that all consumers of the static shared library have changed
-                    mPm.sendPackageChangedBroadcast(pkg.getPackageName(), false /* dontKillApp */,
+                    mPm.sendPackageChangedBroadcast(pkg.getPackageName(), dontKillApp,
                             new ArrayList<>(Collections.singletonList(pkg.getPackageName())),
                             pkg.getUid(), null);
                 }
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index c8bd2c0..a380344 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -497,7 +497,7 @@
      *
      * @throws InstallerException if {@code dexopt} fails.
      */
-    public boolean dexopt(String apkPath, int uid, @Nullable String pkgName, String instructionSet,
+    public boolean dexopt(String apkPath, int uid, String pkgName, String instructionSet,
             int dexoptNeeded, @Nullable String outputPath, int dexFlags,
             String compilerFilter, @Nullable String volumeUuid, @Nullable String classLoaderContext,
             @Nullable String seInfo, boolean downgrade, int targetSdkVersion,
@@ -585,11 +585,14 @@
         }
     }
 
-    public void rmPackageDir(String packageDir) throws InstallerException {
+    /**
+     * Remove a directory belonging to a package.
+     */
+    public void rmPackageDir(String packageName, String packageDir) throws InstallerException {
         if (!checkBeforeRemote()) return;
         BlockGuard.getVmPolicy().onPathAccess(packageDir);
         try {
-            mInstalld.rmPackageDir(packageDir);
+            mInstalld.rmPackageDir(packageName, packageDir);
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
@@ -662,35 +665,44 @@
         }
     }
 
-    public void createOatDir(String oatDir, String dexInstructionSet)
+    /**
+     * Creates an oat dir for given package and instruction set.
+     */
+    public void createOatDir(String packageName, String oatDir, String dexInstructionSet)
             throws InstallerException {
         if (!checkBeforeRemote()) return;
         try {
-            mInstalld.createOatDir(oatDir, dexInstructionSet);
+            mInstalld.createOatDir(packageName, oatDir, dexInstructionSet);
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
     }
 
-    public void linkFile(String relativePath, String fromBase, String toBase)
+    /**
+     * Creates a hardlink for a path.
+     */
+    public void linkFile(String packageName, String relativePath, String fromBase, String toBase)
             throws InstallerException {
         if (!checkBeforeRemote()) return;
         BlockGuard.getVmPolicy().onPathAccess(fromBase);
         BlockGuard.getVmPolicy().onPathAccess(toBase);
         try {
-            mInstalld.linkFile(relativePath, fromBase, toBase);
+            mInstalld.linkFile(packageName, relativePath, fromBase, toBase);
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
     }
 
-    public void moveAb(String apkPath, String instructionSet, String outputPath)
+    /**
+     * Moves oat/vdex/art from "B" set defined by ro.boot.slot_suffix to the default set.
+     */
+    public void moveAb(String packageName, String apkPath, String instructionSet, String outputPath)
             throws InstallerException {
         if (!checkBeforeRemote()) return;
         BlockGuard.getVmPolicy().onPathAccess(apkPath);
         BlockGuard.getVmPolicy().onPathAccess(outputPath);
         try {
-            mInstalld.moveAb(apkPath, instructionSet, outputPath);
+            mInstalld.moveAb(packageName, apkPath, instructionSet, outputPath);
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
@@ -700,35 +712,41 @@
      * Deletes the optimized artifacts generated by ART and returns the number
      * of freed bytes.
      */
-    public long deleteOdex(String apkPath, String instructionSet, String outputPath)
-            throws InstallerException {
+    public long deleteOdex(String packageName, String apkPath, String instructionSet,
+            String outputPath) throws InstallerException {
         if (!checkBeforeRemote()) return -1;
         BlockGuard.getVmPolicy().onPathAccess(apkPath);
         BlockGuard.getVmPolicy().onPathAccess(outputPath);
         try {
-            return mInstalld.deleteOdex(apkPath, instructionSet, outputPath);
+            return mInstalld.deleteOdex(packageName, apkPath, instructionSet, outputPath);
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
     }
 
-    public void installApkVerity(String filePath, FileDescriptor verityInput, int contentSize)
-            throws InstallerException {
+    /**
+     * Enables legacy apk-verity for an apk.
+     */
+    public void installApkVerity(String packageName, String filePath, FileDescriptor verityInput,
+            int contentSize) throws InstallerException {
         if (!checkBeforeRemote()) return;
         BlockGuard.getVmPolicy().onPathAccess(filePath);
         try {
-            mInstalld.installApkVerity(filePath, verityInput, contentSize);
+            mInstalld.installApkVerity(packageName, filePath, verityInput, contentSize);
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
     }
 
-    public void assertFsverityRootHashMatches(String filePath, @NonNull byte[] expectedHash)
-            throws InstallerException {
+    /**
+     * Checks if provided hash matches the file's fs-verity merkle tree root hash.
+     */
+    public void assertFsverityRootHashMatches(String packageName, String filePath,
+            @NonNull byte[] expectedHash) throws InstallerException {
         if (!checkBeforeRemote()) return;
         BlockGuard.getVmPolicy().onPathAccess(filePath);
         try {
-            mInstalld.assertFsverityRootHashMatches(filePath, expectedHash);
+            mInstalld.assertFsverityRootHashMatches(packageName, filePath, expectedHash);
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 9e6f4f7..c125fe1 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -411,6 +411,7 @@
             final List<String> paths =
                     AndroidPackageUtils.getAllCodePathsExcludingResourceOnly(pkg);
             final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
+            final String packageName = pkg.getPackageName();
             for (String dexCodeInstructionSet : dexCodeInstructionSets) {
                 for (String path : paths) {
                     String oatDir = PackageDexOptimizer.getOatDir(
@@ -420,7 +421,7 @@
 
                     packagePaths++;
                     try {
-                        installer.moveAb(path, dexCodeInstructionSet, oatDir);
+                        installer.moveAb(packageName, path, dexCodeInstructionSet, oatDir);
                         pathsSuccessful++;
                     } catch (InstallerException e) {
                     }
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index de1c2ad..7c8515b 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -123,6 +123,8 @@
     private static final String TAG = "PackageInstaller";
     private static final boolean LOGD = false;
 
+    private static final boolean DEBUG = Build.IS_DEBUGGABLE;
+
     // TODO: remove outstanding sessions when installer package goes away
     // TODO: notify listeners in other users when package has been installed there
     // TODO: purge expired sessions periodically in addition to at reboot
@@ -411,13 +413,6 @@
         removeStagingDirs(unclaimedStagingDirsOnVolume);
     }
 
-    public static boolean isStageName(String name) {
-        final boolean isFile = name.startsWith("vmdl") && name.endsWith(".tmp");
-        final boolean isContainer = name.startsWith("smdl") && name.endsWith(".tmp");
-        final boolean isLegacyContainer = name.startsWith("smdl2tmp");
-        return isFile || isContainer || isLegacyContainer;
-    }
-
     @Deprecated
     public File allocateStageDirLegacy(String volumeUuid, boolean isEphemeral) throws IOException {
         synchronized (mSessions) {
@@ -935,6 +930,23 @@
         throw new IllegalStateException("Failed to allocate session ID");
     }
 
+    static boolean isStageName(String name) {
+        final boolean isFile = name.startsWith("vmdl") && name.endsWith(".tmp");
+        final boolean isContainer = name.startsWith("smdl") && name.endsWith(".tmp");
+        final boolean isLegacyContainer = name.startsWith("smdl2tmp");
+        return isFile || isContainer || isLegacyContainer;
+    }
+
+    static int tryParseSessionId(@NonNull String tmpSessionDir)
+            throws IllegalArgumentException {
+        if (!tmpSessionDir.startsWith("vmdl") || !tmpSessionDir.endsWith(".tmp")) {
+            throw new IllegalArgumentException("Not a temporary session directory");
+        }
+        String sessionId = tmpSessionDir.substring("vmdl".length(),
+                tmpSessionDir.length() - ".tmp".length());
+        return Integer.parseInt(sessionId);
+    }
+
     private File getTmpSessionDir(String volumeUuid) {
         return Environment.getDataAppDirectory(volumeUuid);
     }
@@ -949,7 +961,12 @@
             final File sessionStagingDir = Environment.getDataStagingDirectory(params.volumeUuid);
             return new File(sessionStagingDir, "session_" + sessionId);
         }
-        return buildTmpSessionDir(sessionId, params.volumeUuid);
+        final File result = buildTmpSessionDir(sessionId, params.volumeUuid);
+        if (DEBUG && !Objects.equals(tryParseSessionId(result.getName()), sessionId)) {
+            throw new RuntimeException(
+                    "session folder format is off: " + result.getName() + " (" + sessionId + ")");
+        }
+        return result;
     }
 
     static void prepareStageDir(File stageDir) throws IOException {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 7fd7505..dbbc163 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -70,6 +70,7 @@
 import android.content.pm.FileSystemControlParcel;
 import android.content.pm.IDataLoader;
 import android.content.pm.IDataLoaderStatusListener;
+import android.content.pm.IOnChecksumsReadyListener;
 import android.content.pm.IPackageInstallObserver2;
 import android.content.pm.IPackageInstallerSession;
 import android.content.pm.IPackageInstallerSessionFileSystemConnector;
@@ -166,6 +167,7 @@
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileFilter;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.security.NoSuchAlgorithmException;
@@ -558,7 +560,7 @@
                 Slog.d(TAG, "Marking session " + sessionId + " as failed: " + errorMessage);
                 childSessions = getChildSessionsLocked();
             }
-            cleanStageDir(childSessions);
+            destroy();
             mCallback.onStagedSessionChanged(PackageInstallerSession.this);
         }
 
@@ -576,7 +578,7 @@
                 Slog.d(TAG, "Marking session " + sessionId + " as applied");
                 childSessions = getChildSessionsLocked();
             }
-            cleanStageDir(childSessions);
+            destroy();
             mCallback.onStagedSessionChanged(PackageInstallerSession.this);
         }
 
@@ -699,13 +701,11 @@
                     return;
                 }
                 mDestroyed = true;
-                List<PackageInstallerSession> childSessions = getChildSessionsLocked();
                 r = () -> {
                     assertNotLocked("abandonStaged");
                     if (mCommitted.get()) {
                         mStagingManager.abortCommittedSession(this);
                     }
-                    cleanStageDir(childSessions);
                     destroyInternal();
                     dispatchSessionFinished(INSTALL_FAILED_ABORTED, "Session was abandoned", null);
                     maybeCleanUpChildSessions();
@@ -1399,6 +1399,20 @@
     }
 
     @Override
+    public void requestChecksums(@NonNull String name, @Checksum.TypeMask int optional,
+            @Checksum.TypeMask int required, @Nullable List trustedInstallers,
+            @NonNull IOnChecksumsReadyListener onChecksumsReadyListener) {
+        final File file = new File(stageDir, name);
+        final String installerPackageName = getInstallSource().initiatingPackageName;
+        try {
+            mPm.requestFileChecksums(file, installerPackageName, optional, required,
+                    trustedInstallers, onChecksumsReadyListener);
+        } catch (FileNotFoundException e) {
+            throw new ParcelableException(e);
+        }
+    }
+
+    @Override
     public void removeSplit(String splitName) {
         if (isDataLoaderInstallation()) {
             throw new IllegalStateException(
@@ -2102,27 +2116,19 @@
         destroyInternal();
         // Dispatch message to remove session from PackageInstallerService.
         dispatchSessionFinished(error, detailMessage, null);
-        // TODO(b/173194203): clean up staged session in destroyInternal() call instead
-        if (isStaged() && stageDir != null) {
-            cleanStageDir();
-        }
     }
 
     private void onSessionVerificationFailure(int error, String msg) {
         final String msgWithErrorCode = PackageManager.installStatusToString(error, msg);
         Slog.e(TAG, "Failed to verify session " + sessionId + " [" + msgWithErrorCode + "]");
-        // Session is sealed and committed but could not be verified, we need to destroy it.
-        destroyInternal();
-        if (isMultiPackage()) {
-            for (PackageInstallerSession childSession : getChildSessions()) {
-                childSession.destroyInternal();
-            }
-        }
         if (isStaged()) {
+            // This will clean up the session when it reaches the terminal state
             mStagedSession.setSessionFailed(
                     SessionInfo.STAGED_SESSION_VERIFICATION_FAILED, msgWithErrorCode);
             mStagedSession.notifyEndPreRebootVerification();
         } else {
+            // Session is sealed and committed but could not be verified, we need to destroy it.
+            destroy();
             // Dispatch message to remove session from PackageInstallerService.
             dispatchSessionFinished(error, msg, null);
         }
@@ -2412,6 +2418,7 @@
             try {
                 final List<File> fromFiles = mResolvedInheritedFiles;
                 final File toDir = stageDir;
+                final String tempPackageName = toDir.getName();
 
                 if (LOGD) Slog.d(TAG, "Inherited files: " + mResolvedInheritedFiles);
                 if (!mResolvedInheritedFiles.isEmpty() && mInheritedFilesBase == null) {
@@ -2421,7 +2428,7 @@
                 if (isLinkPossible(fromFiles, toDir)) {
                     if (!mResolvedInstructionSets.isEmpty()) {
                         final File oatDir = new File(toDir, "oat");
-                        createOatDirs(mResolvedInstructionSets, oatDir);
+                        createOatDirs(tempPackageName, mResolvedInstructionSets, oatDir);
                     }
                     // pre-create lib dirs for linking if necessary
                     if (!mResolvedNativeLibPaths.isEmpty()) {
@@ -2444,7 +2451,7 @@
                                     new File(libDir, archDirPath));
                         }
                     }
-                    linkFiles(fromFiles, toDir, mInheritedFilesBase);
+                    linkFiles(tempPackageName, fromFiles, toDir, mInheritedFilesBase);
                 } else {
                     // TODO: this should delegate to DCS so the system process
                     // avoids holding open FDs into containers.
@@ -3539,18 +3546,19 @@
         throw new IOException("File: " + pathStr + " outside base: " + baseStr);
     }
 
-    private void createOatDirs(List<String> instructionSets, File fromDir)
+    private void createOatDirs(String packageName, List<String> instructionSets, File fromDir)
             throws PackageManagerException {
         for (String instructionSet : instructionSets) {
             try {
-                mInstaller.createOatDir(fromDir.getAbsolutePath(), instructionSet);
+                mInstaller.createOatDir(packageName, fromDir.getAbsolutePath(), instructionSet);
             } catch (InstallerException e) {
                 throw PackageManagerException.from(e);
             }
         }
     }
 
-    private void linkFile(String relativePath, String fromBase, String toBase) throws IOException {
+    private void linkFile(String packageName, String relativePath, String fromBase, String toBase)
+            throws IOException {
         try {
             // Try
             final IncrementalFileStorages incrementalFileStorages = getIncrementalFileStorages();
@@ -3558,21 +3566,21 @@
                     fromBase, toBase)) {
                 return;
             }
-            mInstaller.linkFile(relativePath, fromBase, toBase);
+            mInstaller.linkFile(packageName, relativePath, fromBase, toBase);
         } catch (InstallerException | IOException e) {
             throw new IOException("failed linkOrCreateDir(" + relativePath + ", "
                     + fromBase + ", " + toBase + ")", e);
         }
     }
 
-    private void linkFiles(List<File> fromFiles, File toDir, File fromDir)
+    private void linkFiles(String packageName, List<File> fromFiles, File toDir, File fromDir)
             throws IOException {
         for (File fromFile : fromFiles) {
             final String relativePath = getRelativePath(fromFile, fromDir);
             final String fromBase = fromDir.getAbsolutePath();
             final String toBase = toDir.getAbsolutePath();
 
-            linkFile(relativePath, fromBase, toBase);
+            linkFile(packageName, relativePath, fromBase, toBase);
         }
 
         Slog.d(TAG, "Linked " + fromFiles.size() + " files into " + toDir);
@@ -4265,6 +4273,28 @@
         return params.isStaged ? mStagedSession.getSessionErrorMessage() : "";
     }
 
+    /**
+     * Free up storage used by this session and its children.
+     * Must not be called on a child session.
+     */
+    private void destroy() {
+        // TODO(b/173194203): destroy() is called indirectly by
+        //  PackageInstallerService#restoreAndApplyStagedSessionIfNeeded on an orphan child session.
+        //  Enable this assertion when we figure out a better way to clean up orphan sessions.
+        // assertNotChild("destroy");
+
+        // TODO(b/173194203): destroyInternal() should be used by destroy() only.
+        //  For the sake of consistency, a session should be destroyed as a whole. The caller
+        //  should always call destroy() for cleanup without knowing it has child sessions or not.
+        destroyInternal();
+        for (PackageInstallerSession child : getChildSessions()) {
+            child.destroyInternal();
+        }
+    }
+
+    /**
+     * Free up storage used by this session.
+     */
     private void destroyInternal() {
         final IncrementalFileStorages incrementalFileStorages;
         synchronized (mLock) {
@@ -4282,41 +4312,14 @@
             incrementalFileStorages = mIncrementalFileStorages;
             mIncrementalFileStorages = null;
         }
-        // For staged sessions, we don't delete the directory where the packages have been copied,
-        // since these packages are supposed to be read on reboot.
-        // Those dirs are deleted when the staged session has reached a final state.
-        if (stageDir != null && !params.isStaged) {
-            try {
-                if (incrementalFileStorages != null) {
-                    incrementalFileStorages.cleanUpAndMarkComplete();
-                }
-                mInstaller.rmPackageDir(stageDir.getAbsolutePath());
-            } catch (InstallerException ignored) {
-            }
-        }
-    }
-
-    private void cleanStageDir(List<PackageInstallerSession> childSessions) {
-        if (isMultiPackage()) {
-            for (PackageInstallerSession childSession : childSessions) {
-                childSession.cleanStageDir();
-            }
-        } else {
-            cleanStageDir();
-        }
-    }
-
-    private void cleanStageDir() {
-        final IncrementalFileStorages incrementalFileStorages;
-        synchronized (mLock) {
-            incrementalFileStorages = mIncrementalFileStorages;
-            mIncrementalFileStorages = null;
-        }
         try {
             if (incrementalFileStorages != null) {
                 incrementalFileStorages.cleanUpAndMarkComplete();
             }
-            mInstaller.rmPackageDir(stageDir.getAbsolutePath());
+            if (stageDir != null) {
+                final String tempPackageName = stageDir.getName();
+                mInstaller.rmPackageDir(tempPackageName, stageDir.getAbsolutePath());
+            }
         } catch (InstallerException ignored) {
         }
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 400f03b..9f5adcb 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -262,6 +262,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintWriter;
@@ -554,6 +555,7 @@
     public static final int REASON_LAST = REASON_SHARED;
 
     static final String RANDOM_DIR_PREFIX = "~~";
+    static final char RANDOM_CODEPATH_PREFIX = '-';
 
     final Handler mHandler;
 
@@ -1261,15 +1263,50 @@
     }
 
     @Override
-    public void requestChecksums(@NonNull String packageName, boolean includeSplits,
-            @Checksum.TypeMask int optional,
-            @Checksum.TypeMask int required, @Nullable List trustedInstallers,
+    public void requestPackageChecksums(@NonNull String packageName, boolean includeSplits,
+            @Checksum.TypeMask int optional, @Checksum.TypeMask int required,
+            @Nullable List trustedInstallers,
             @NonNull IOnChecksumsReadyListener onChecksumsReadyListener, int userId) {
         requestChecksumsInternal(packageName, includeSplits, optional, required, trustedInstallers,
                 onChecksumsReadyListener, userId, mInjector.getBackgroundExecutor(),
                 mInjector.getBackgroundHandler());
     }
 
+    /**
+     * Requests checksums for the APK file.
+     * See {@link PackageInstaller.Session#requestChecksums} for details.
+     */
+    public void requestFileChecksums(@NonNull File file,
+            @NonNull String installerPackageName, @Checksum.TypeMask int optional,
+            @Checksum.TypeMask int required, @Nullable List trustedInstallers,
+            @NonNull IOnChecksumsReadyListener onChecksumsReadyListener)
+            throws FileNotFoundException {
+        if (!file.exists()) {
+            throw new FileNotFoundException(file.getAbsolutePath());
+        }
+        if (TextUtils.isEmpty(installerPackageName)) {
+            throw new FileNotFoundException(file.getAbsolutePath());
+        }
+
+        final Executor executor = mInjector.getBackgroundExecutor();
+        final Handler handler = mInjector.getBackgroundHandler();
+        final Certificate[] trustedCerts = (trustedInstallers != null) ? decodeCertificates(
+                trustedInstallers) : null;
+
+        final List<Pair<String, File>> filesToChecksum = new ArrayList<>(1);
+        filesToChecksum.add(Pair.create(null, file));
+
+        executor.execute(() -> {
+            ApkChecksums.Injector injector = new ApkChecksums.Injector(
+                    () -> mContext,
+                    () -> handler,
+                    () -> mInjector.getIncrementalManager(),
+                    () -> mPmInternal);
+            ApkChecksums.getChecksums(filesToChecksum, optional, required, installerPackageName,
+                    trustedCerts, onChecksumsReadyListener, injector);
+        });
+    }
+
     private void requestChecksumsInternal(@NonNull String packageName, boolean includeSplits,
             @Checksum.TypeMask int optional, @Checksum.TypeMask int required,
             @Nullable List trustedInstallers,
@@ -1486,30 +1523,33 @@
                 new DefaultSystemWrapper(),
                 LocalServices::getService,
                 context::getSystemService,
-                (i, pm) -> new BackgroundDexOptService(i.getContext(), i.getDexManager()));
+                (i, pm) -> new BackgroundDexOptService(i.getContext(), i.getDexManager(), pm));
 
         if (Build.VERSION.SDK_INT <= 0) {
             Slog.w(TAG, "**** ro.build.version.sdk not set!");
         }
 
         PackageManagerService m = new PackageManagerService(injector, onlyCore, factoryTest,
-                Build.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG, Build.VERSION.SDK_INT,
-                Build.VERSION.INCREMENTAL, SNAPSHOT_ENABLED);
+                PackagePartitions.FINGERPRINT, Build.IS_ENG, Build.IS_USERDEBUG,
+                Build.VERSION.SDK_INT, Build.VERSION.INCREMENTAL, SNAPSHOT_ENABLED);
         t.traceEnd(); // "create package manager"
 
         final CompatChange.ChangeListener selinuxChangeListener = packageName -> {
             synchronized (m.mInstallLock) {
                 final AndroidPackage pkg;
+                final PackageSetting ps;
                 final SharedUserSetting sharedUser;
                 final String oldSeInfo;
-                final PackageStateInternal packageState = m.getPackageStateInternal(packageName);
-                if (packageState == null) {
-                    Slog.e(TAG, "Failed to find package setting " + packageName);
-                    return;
+                synchronized (m.mLock) {
+                    ps = m.mSettings.getPackageLPr(packageName);
+                    if (ps == null) {
+                        Slog.e(TAG, "Failed to find package setting " + packageName);
+                        return;
+                    }
+                    pkg = ps.getPkg();
+                    sharedUser = ps.getSharedUser();
+                    oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps);
                 }
-                pkg = packageState.getPkg();
-                sharedUser = packageState.getSharedUser();
-                oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, packageState);
 
                 if (pkg == null) {
                     Slog.e(TAG, "Failed to find package " + packageName);
@@ -1521,7 +1561,7 @@
                 if (!newSeInfo.equals(oldSeInfo)) {
                     Slog.i(TAG, "Updating seInfo for package " + packageName + " from: "
                             + oldSeInfo + " to: " + newSeInfo);
-                    packageState.getTransientState().setOverrideSeInfo(newSeInfo);
+                    ps.getPkgState().setOverrideSeInfo(newSeInfo);
                     m.mAppDataHelper.prepareAppDataAfterInstallLIF(pkg);
                 }
             }
@@ -1904,8 +1944,8 @@
             mIsUpgrade =
                     !buildFingerprint.equals(ver.fingerprint);
             if (mIsUpgrade) {
-                PackageManagerServiceUtils.logCriticalInfo(Log.INFO,
-                        "Upgrading from " + ver.fingerprint + " to " + Build.FINGERPRINT);
+                PackageManagerServiceUtils.logCriticalInfo(Log.INFO, "Upgrading from "
+                        + ver.fingerprint + " to " + PackagePartitions.FINGERPRINT);
             }
 
             // when upgrading from pre-M, promote system app permissions from install to runtime
@@ -2003,7 +2043,8 @@
             // this situation.
             if (mIsUpgrade) {
                 Slog.i(TAG, "Build fingerprint changed from " + ver.fingerprint + " to "
-                        + Build.FINGERPRINT + "; regranting permissions for internal storage");
+                        + PackagePartitions.FINGERPRINT
+                        + "; regranting permissions for internal storage");
             }
             mPermissionManager.onStorageVolumeMounted(
                     StorageManager.UUID_PRIVATE_INTERNAL, mIsUpgrade);
@@ -2037,7 +2078,7 @@
                                         | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES);
                     }
                 }
-                ver.fingerprint = Build.FINGERPRINT;
+                ver.fingerprint = PackagePartitions.FINGERPRINT;
             }
 
             // Legacy existing (installed before Q) non-system apps to hide
@@ -5663,6 +5704,9 @@
                         synchronized (mLock) {
                             mInstantAppRegistry.deleteInstantApplicationMetadataLPw(
                                     packageName, userId);
+                            if (succeeded) {
+                                resetComponentEnabledSettingsIfNeededLPw(packageName, userId);
+                            }
                         }
                     }
                     if (succeeded) {
@@ -5739,6 +5783,62 @@
     }
 
     /**
+     * Update component enabled settings to {@link PackageManager#COMPONENT_ENABLED_STATE_DEFAULT}
+     * if the resetEnabledSettingsOnAppDataCleared is {@code true}.
+     */
+    private void resetComponentEnabledSettingsIfNeededLPw(String packageName, int userId) {
+        final AndroidPackage pkg = packageName != null ? mPackages.get(packageName) : null;
+        if (pkg == null || !pkg.isResetEnabledSettingsOnAppDataCleared()) {
+            return;
+        }
+        final PackageSetting pkgSetting = mSettings.getPackageLPr(packageName);
+        if (pkgSetting == null) {
+            return;
+        }
+        final ArrayList<String> updatedComponents = new ArrayList<>();
+        final Consumer<? super ParsedMainComponent> resetSettings = (component) -> {
+            if (pkgSetting.restoreComponentLPw(component.getClassName(), userId)) {
+                updatedComponents.add(component.getClassName());
+            }
+        };
+        for (int i = 0; i < pkg.getActivities().size(); i++) {
+            resetSettings.accept(pkg.getActivities().get(i));
+        }
+        for (int i = 0; i < pkg.getReceivers().size(); i++) {
+            resetSettings.accept(pkg.getReceivers().get(i));
+        }
+        for (int i = 0; i < pkg.getServices().size(); i++) {
+            resetSettings.accept(pkg.getServices().get(i));
+        }
+        for (int i = 0; i < pkg.getProviders().size(); i++) {
+            resetSettings.accept(pkg.getProviders().get(i));
+        }
+        if (ArrayUtils.isEmpty(updatedComponents)) {
+            // nothing changed
+            return;
+        }
+
+        updateSequenceNumberLP(pkgSetting, new int[] { userId });
+        updateInstantAppInstallerLocked(packageName);
+        scheduleWritePackageRestrictionsLocked(userId);
+
+        final ArrayList<String> pendingComponents = mPendingBroadcasts.get(userId, packageName);
+        if (pendingComponents == null) {
+            mPendingBroadcasts.put(userId, packageName, updatedComponents);
+        } else {
+            for (int i = 0; i < updatedComponents.size(); i++) {
+                final String updatedComponent = updatedComponents.get(i);
+                if (!pendingComponents.contains(updatedComponent)) {
+                    pendingComponents.add(updatedComponent);
+                }
+            }
+        }
+        if (!mHandler.hasMessages(SEND_PENDING_BROADCAST)) {
+            mHandler.sendEmptyMessageDelayed(SEND_PENDING_BROADCAST, BROADCAST_DELAY);
+        }
+    }
+
+    /**
      * Remove entries from the keystore daemon. Will only remove it if the
      * {@code appId} is valid.
      */
@@ -6806,24 +6906,24 @@
         }
         enforceCrossUserPermission(callingUid, userId, true /* requireFullPermission */,
                 true /* checkShell */, "stop package");
-        boolean shouldUnhibernate = false;
         // writer
         synchronized (mLock) {
             final PackageSetting ps = mSettings.getPackageLPr(packageName);
-            if (ps != null && ps.getStopped(userId) && !stopped) {
-                shouldUnhibernate = true;
-            }
             if (!shouldFilterApplication(ps, callingUid, userId)
                     && mSettings.setPackageStoppedStateLPw(this, packageName, stopped, userId)) {
                 scheduleWritePackageRestrictionsLocked(userId);
             }
         }
-        if (shouldUnhibernate) {
+        // If this would cause the app to leave force-stop, then also make sure to unhibernate the
+        // app if needed.
+        if (!stopped) {
             mHandler.post(() -> {
                 AppHibernationManagerInternal ah =
                         mInjector.getLocalService(AppHibernationManagerInternal.class);
-                ah.setHibernatingForUser(packageName, userId, false);
-                ah.setHibernatingGlobally(packageName, false);
+                if (ah != null && ah.isHibernatingForUser(packageName, userId)) {
+                    ah.setHibernatingForUser(packageName, userId, false);
+                    ah.setHibernatingGlobally(packageName, false);
+                }
             });
         }
     }
@@ -8220,8 +8320,8 @@
         @Override
         public @PackageManager.EnabledState int getComponentEnabledSetting(
                 @NonNull ComponentName componentName, int callingUid, int userId) {
-            return PackageManagerService.this.mComputer.getComponentEnabledSetting(componentName,
-                    callingUid, userId);
+            return PackageManagerService.this.mComputer.getComponentEnabledSettingInternal(
+                    componentName, callingUid, userId);
         }
 
         @Override
@@ -8962,9 +9062,12 @@
     @Override
     public void setSplashScreenTheme(@NonNull String packageName, @Nullable String themeId,
             int userId) {
-        mutateInstalledPackageSetting(packageName, Binder.getCallingUid(), userId, pkgSetting -> {
-            pkgSetting.setSplashScreenTheme(userId, themeId);
-        });
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */,
+                false /* checkShell */, "setSplashScreenTheme");
+        enforceOwnerRights(packageName, callingUid);
+        mutateInstalledPackageSetting(packageName, callingUid, userId,
+                pkgSetting -> pkgSetting.setSplashScreenTheme(userId, themeId));
     }
 
     @Override
@@ -9339,7 +9442,8 @@
                 mResolveActivity.processName = "system:ui";
                 mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
                 mResolveActivity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NEVER;
-                mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
+                mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS
+                        | ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
                 mResolveActivity.theme = R.style.Theme_Material_Dialog_Alert;
                 mResolveActivity.exported = true;
                 mResolveActivity.enabled = true;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index bf0383a..3b643b5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -25,6 +25,7 @@
 import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
 import static com.android.server.pm.PackageManagerService.DEBUG_INTENT_MATCHING;
 import static com.android.server.pm.PackageManagerService.DEBUG_PREFERRED;
+import static com.android.server.pm.PackageManagerService.RANDOM_CODEPATH_PREFIX;
 import static com.android.server.pm.PackageManagerService.RANDOM_DIR_PREFIX;
 import static com.android.server.pm.PackageManagerService.STUB_SUFFIX;
 import static com.android.server.pm.PackageManagerService.TAG;
@@ -41,6 +42,7 @@
 import android.content.pm.ComponentInfo;
 import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageManager;
+import android.content.pm.PackagePartitions;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.Signature;
@@ -67,6 +69,7 @@
 import android.system.ErrnoException;
 import android.system.Os;
 import android.util.ArraySet;
+import android.util.AtomicFile;
 import android.util.Base64;
 import android.util.Log;
 import android.util.LogPrinter;
@@ -100,7 +103,6 @@
 import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.nio.file.Path;
 import java.security.SecureRandom;
@@ -123,6 +125,8 @@
 public class PackageManagerServiceUtils {
     private static final long MAX_CRITICAL_INFO_DUMP_SIZE = 3 * 1000 * 1000; // 3MB
 
+    private static final boolean DEBUG = Build.IS_DEBUGGABLE;
+
     public final static Predicate<PackageStateInternal> REMOVE_IF_NULL_PKG =
             pkgSetting -> pkgSetting.getPkg() == null;
 
@@ -679,17 +683,23 @@
                     + "; src: " + srcFile.getAbsolutePath()
                     + ", dst: " + dstFile.getAbsolutePath());
         }
+        final AtomicFile atomicFile = new AtomicFile(dstFile);
+        FileOutputStream outputStream = null;
         try (
-                InputStream fileIn = new GZIPInputStream(new FileInputStream(srcFile));
-                OutputStream fileOut = new FileOutputStream(dstFile, false /*append*/);
+                InputStream fileIn = new GZIPInputStream(new FileInputStream(srcFile))
         ) {
-            FileUtils.copy(fileIn, fileOut);
-            Os.chmod(dstFile.getAbsolutePath(), 0644);
+            outputStream = atomicFile.startWrite();
+            FileUtils.copy(fileIn, outputStream);
+            // Flush anything in buffer before chmod, because any writes after chmod will fail.
+            outputStream.flush();
+            Os.fchmod(outputStream.getFD(), 0644);
+            atomicFile.finishWrite(outputStream);
             return PackageManager.INSTALL_SUCCEEDED;
         } catch (IOException e) {
             logCriticalInfo(Log.ERROR, "Failed to decompress file"
                     + "; src: " + srcFile.getAbsolutePath()
                     + ", dst: " + dstFile.getAbsolutePath());
+            atomicFile.failWrite(outputStream);
         }
         return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
     }
@@ -1116,13 +1126,28 @@
         File firstLevelDir;
         do {
             random.nextBytes(bytes);
-            String dirName = RANDOM_DIR_PREFIX
+            String firstLevelDirName = RANDOM_DIR_PREFIX
                     + Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP);
-            firstLevelDir = new File(targetDir, dirName);
+            firstLevelDir = new File(targetDir, firstLevelDirName);
         } while (firstLevelDir.exists());
+
         random.nextBytes(bytes);
-        String suffix = Base64.encodeToString(bytes, Base64.URL_SAFE | Base64.NO_WRAP);
-        return new File(firstLevelDir, packageName + "-" + suffix);
+        String dirName = packageName + RANDOM_CODEPATH_PREFIX + Base64.encodeToString(bytes,
+                Base64.URL_SAFE | Base64.NO_WRAP);
+        final File result = new File(firstLevelDir, dirName);
+        if (DEBUG && !Objects.equals(tryParsePackageName(result.getName()), packageName)) {
+            throw new RuntimeException(
+                    "codepath is off: " + result.getName() + " (" + packageName + ")");
+        }
+        return result;
+    }
+
+    static String tryParsePackageName(@NonNull String codePath) throws IllegalArgumentException {
+        int packageNameEnds = codePath.indexOf(RANDOM_CODEPATH_PREFIX);
+        if (packageNameEnds == -1) {
+            throw new IllegalArgumentException("Not a valid package folder name");
+        }
+        return codePath.substring(0, packageNameEnds);
     }
 
     /**
@@ -1209,7 +1234,7 @@
         // identify cached items. In particular, changing the value of certain
         // feature flags should cause us to invalidate any caches.
         final String cacheName = FORCE_PACKAGE_PARSED_CACHE_ENABLED ? "debug"
-                : SystemProperties.digestOf("ro.build.fingerprint");
+                : PackagePartitions.FINGERPRINT;
 
         // Reconcile cache directories, keeping only what we'd actually use.
         for (File cacheDir : FileUtils.listFilesOrEmpty(cacheBaseDir)) {
diff --git a/services/core/java/com/android/server/pm/PackageSessionVerifier.java b/services/core/java/com/android/server/pm/PackageSessionVerifier.java
index 866712c..4f21d0e 100644
--- a/services/core/java/com/android/server/pm/PackageSessionVerifier.java
+++ b/services/core/java/com/android/server/pm/PackageSessionVerifier.java
@@ -527,6 +527,9 @@
     @VisibleForTesting
     void checkRollbacks(StagingManager.StagedSession session)
             throws PackageManagerException {
+        if (session.isDestroyed() || session.isInTerminalState()) {
+            return;
+        }
         for (StagingManager.StagedSession stagedSession : mStagedSessions) {
             if (stagedSession.isDestroyed() || stagedSession.isInTerminalState()) {
                 continue;
@@ -565,6 +568,9 @@
     @VisibleForTesting
     void checkOverlaps(StagingManager.StagedSession parent,
             StagingManager.StagedSession child) throws PackageManagerException {
+        if (parent.isDestroyed() || parent.isInTerminalState()) {
+            return;
+        }
         final String packageName = child.getPackageName();
         if (packageName == null) {
             throw new PackageManagerException(
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index 3a2ac1c..48b893b 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -94,9 +94,10 @@
                     }
                 }
 
-                mInstaller.rmPackageDir(codePath.getAbsolutePath());
+                final String packageName = codePath.getName();
+                mInstaller.rmPackageDir(packageName, codePath.getAbsolutePath());
                 if (needRemoveParent) {
-                    mInstaller.rmPackageDir(codePathParent.getAbsolutePath());
+                    mInstaller.rmPackageDir(packageName, codePathParent.getAbsolutePath());
                     removeCachedResult(codePathParent);
                 }
             } catch (Installer.InstallerException e) {
diff --git a/services/core/java/com/android/server/pm/ScanPackageHelper.java b/services/core/java/com/android/server/pm/ScanPackageHelper.java
index 6cc94ce..9b08ef9 100644
--- a/services/core/java/com/android/server/pm/ScanPackageHelper.java
+++ b/services/core/java/com/android/server/pm/ScanPackageHelper.java
@@ -894,14 +894,15 @@
      * Returns if forced apk verification can be skipped for the whole package, including splits.
      */
     private boolean canSkipForcedPackageVerification(AndroidPackage pkg) {
-        if (!canSkipForcedApkVerification(pkg.getBaseApkPath())) {
+        final String packageName = pkg.getPackageName();
+        if (!canSkipForcedApkVerification(packageName, pkg.getBaseApkPath())) {
             return false;
         }
         // TODO: Allow base and splits to be verified individually.
         String[] splitCodePaths = pkg.getSplitCodePaths();
         if (!ArrayUtils.isEmpty(splitCodePaths)) {
             for (int i = 0; i < splitCodePaths.length; i++) {
-                if (!canSkipForcedApkVerification(splitCodePaths[i])) {
+                if (!canSkipForcedApkVerification(packageName, splitCodePaths[i])) {
                     return false;
                 }
             }
@@ -914,7 +915,7 @@
      * whether the apk contains signed root hash.  Note that the signer's certificate still needs to
      * match one in a trusted source, and should be done separately.
      */
-    private boolean canSkipForcedApkVerification(String apkPath) {
+    private boolean canSkipForcedApkVerification(String packageName, String apkPath) {
         if (!PackageManagerServiceUtils.isLegacyApkVerityEnabled()) {
             return VerityUtils.hasFsverity(apkPath);
         }
@@ -926,7 +927,8 @@
             }
             synchronized (mPm.mInstallLock) {
                 // Returns whether the observed root hash matches what kernel has.
-                mPm.mInstaller.assertFsverityRootHashMatches(apkPath, rootHashObserved);
+                mPm.mInstaller.assertFsverityRootHashMatches(packageName, apkPath,
+                        rootHashObserved);
                 return true;
             }
         } catch (Installer.InstallerException | IOException | DigestException
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 7f2fd56..6a163b2 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -42,6 +42,7 @@
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackagePartitions;
 import android.content.pm.PermissionInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.Signature;
@@ -436,7 +437,7 @@
         public void forceCurrent() {
             sdkVersion = Build.VERSION.SDK_INT;
             databaseVersion = CURRENT_DATABASE_VERSION;
-            fingerprint = Build.FINGERPRINT;
+            fingerprint = PackagePartitions.FINGERPRINT;
         }
     }
 
@@ -5356,7 +5357,7 @@
         }
 
         private String getExtendedFingerprint(long version) {
-            return Build.FINGERPRINT + "?pc_version=" + version;
+            return PackagePartitions.FINGERPRINT + "?pc_version=" + version;
         }
 
         public void writeStateForUserAsyncLPr(int userId) {
diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index 6b88081..1433abd 100644
--- a/services/core/java/com/android/server/pm/StorageEventHelper.java
+++ b/services/core/java/com/android/server/pm/StorageEventHelper.java
@@ -29,10 +29,10 @@
 import android.app.ResourcesManager;
 import android.content.IIntentReceiver;
 import android.content.pm.PackageManager;
+import android.content.pm.PackagePartitions;
 import android.content.pm.UserInfo;
 import android.content.pm.VersionedPackage;
 import android.content.pm.parsing.ParsingPackageUtils;
-import android.os.Build;
 import android.os.Environment;
 import android.os.FileUtils;
 import android.os.UserHandle;
@@ -157,7 +157,7 @@
                     Slog.w(TAG, "Failed to scan " + ps.getPath() + ": " + e.getMessage());
                 }
 
-                if (!Build.FINGERPRINT.equals(ver.fingerprint)) {
+                if (!PackagePartitions.FINGERPRINT.equals(ver.fingerprint)) {
                     appDataHelper.clearAppDataLIF(
                             ps.getPkg(), UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE
                             | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY
@@ -195,10 +195,10 @@
         }
 
         synchronized (mPm.mLock) {
-            final boolean isUpgrade = !Build.FINGERPRINT.equals(ver.fingerprint);
+            final boolean isUpgrade = !PackagePartitions.FINGERPRINT.equals(ver.fingerprint);
             if (isUpgrade) {
                 logCriticalInfo(Log.INFO, "Build fingerprint changed from " + ver.fingerprint
-                        + " to " + Build.FINGERPRINT + "; regranting permissions for "
+                        + " to " + PackagePartitions.FINGERPRINT + "; regranting permissions for "
                         + volumeUuid);
             }
             mPm.mPermissionManager.onStorageVolumeMounted(volumeUuid, isUpgrade);
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index d54acb7..a5a8d5c 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -24,20 +24,6 @@
       "name": "CtsMatchFlagTestCases"
     },
     {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "include-filter": "com.android.server.pm."
-        },
-        {
-          "include-annotation": "android.platform.test.annotations.Presubmit"
-        },
-        {
-          "exclude-annotation": "androidx.test.filters.FlakyTest"
-        }
-      ]
-    },
-    {
       "name": "FrameworksMockingServicesTests",
       "options": [
         {
@@ -46,45 +32,6 @@
       ]
     },
     {
-      "name": "FrameworksServicesTests",
-      "file_patterns": ["(/|^)ShortcutService\\.java"],
-      "options": [
-        {
-          "include-filter": "com.android.server.pm.ShortcutManagerTest1"
-        },
-        {
-          "include-filter": "com.android.server.pm.ShortcutManagerTest2"
-        },
-        {
-          "include-filter": "com.android.server.pm.ShortcutManagerTest3"
-        },
-        {
-          "include-filter": "com.android.server.pm.ShortcutManagerTest4"
-        },
-        {
-          "include-filter": "com.android.server.pm.ShortcutManagerTest5"
-        },
-        {
-          "include-filter": "com.android.server.pm.ShortcutManagerTest6"
-        },
-        {
-          "include-filter": "com.android.server.pm.ShortcutManagerTest7"
-        },
-        {
-          "include-filter": "com.android.server.pm.ShortcutManagerTest8"
-        },
-        {
-          "include-filter": "com.android.server.pm.ShortcutManagerTest9"
-        },
-        {
-          "include-filter": "com.android.server.pm.ShortcutManagerTest10"
-        },
-        {
-          "include-filter": "com.android.server.pm.ShortcutManagerTest11"
-        }
-      ]
-    },
-    {
       "name": "CtsShortcutHostTestCases",
       "file_patterns": ["(/|^)ShortcutService\\.java"]
     },
@@ -188,47 +135,6 @@
     },
     {
       "name": "PackageManagerServiceHostTests"
-    },
-    {
-      "name": "FrameworksServicesTests",
-      "options": [
-        {
-          "install-arg": "-t"
-        },
-        {
-          "include-filter": "com.android.server.pm.UserDataPreparerTest"
-        },
-        {
-          "include-filter": "com.android.server.pm.UserLifecycleStressTest"
-        },
-        {
-          "include-filter": "com.android.server.pm.UserManagerServiceCreateProfileTest"
-        },
-        {
-          "include-filter": "com.android.server.pm.UserManagerServiceIdRecyclingTest"
-        },
-        {
-          "include-filter": "com.android.server.pm.UserManagerServiceTest"
-        },
-        {
-          "include-filter": "com.android.server.pm.UserManagerServiceUserInfoTest"
-        },
-        {
-          "include-filter": "com.android.server.pm.UserManagerServiceUserTypeTest"
-        },
-        {
-          "include-filter": "com.android.server.pm.UserManagerTest"
-        },
-        {
-          "include-filter": "com.android.server.pm.UserRestrictionsUtilsTest"
-        },
-        {
-          "include-filter": "com.android.server.pm.UserSystemPackageInstallerTest"
-        },
-        {
-          "include-filter": "com.android.server.pm.parsing.SystemPartitionParseTest"
-        }
-      ]
     }
   ],
   "imports": [
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 302826f..bc4c8b0 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -20,6 +20,8 @@
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 
 import android.Manifest;
+import android.accounts.Account;
+import android.accounts.AccountManager;
 import android.annotation.ColorRes;
 import android.annotation.DrawableRes;
 import android.annotation.NonNull;
@@ -44,6 +46,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackagePartitions;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.UserInfo;
 import android.content.pm.UserInfo.UserInfoFlag;
@@ -85,6 +88,7 @@
 import android.security.GateKeeper;
 import android.service.gatekeeper.IGateKeeperService;
 import android.stats.devicepolicy.DevicePolicyEnums;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.AtomicFile;
@@ -2393,6 +2397,25 @@
         return count;
     }
 
+    /**
+     * Returns whether more users of the given type can be added (based on how many users of that
+     * type already exist).
+     */
+    @Override
+    public boolean canAddMoreUsersOfType(String userType) {
+        checkManageOrCreateUsersPermission("check if more users can be added.");
+        final UserTypeDetails userTypeDetails = mUserTypes.get(userType);
+        return userTypeDetails != null && canAddMoreUsersOfType(userTypeDetails);
+    }
+
+    /** Returns whether the creation of users of the given user type is enabled on this device. */
+    @Override
+    public boolean isUserTypeEnabled(String userType) {
+        checkManageOrCreateUsersPermission("check if user type is enabled.");
+        final UserTypeDetails userTypeDetails = mUserTypes.get(userType);
+        return userTypeDetails != null && userTypeDetails.isEnabled();
+    }
+
     @Override
     public boolean canAddMoreManagedProfiles(@UserIdInt int userId, boolean allowedToRemoveOne) {
         return canAddMoreProfilesToUser(UserManager.USER_TYPE_PROFILE_MANAGED, userId,
@@ -3512,6 +3535,39 @@
         }
     }
 
+    @Override
+    public UserHandle createUserWithAttributes(
+            String userName, String userType, @UserInfoFlag int flags,
+            Bitmap userIcon,
+            String accountName, String accountType, PersistableBundle accountOptions) {
+        checkManageOrCreateUsersPermission(flags);
+
+        if (someUserHasAccountNoChecks(accountName, accountType)) {
+            throw new ServiceSpecificException(
+                    UserManager.USER_OPERATION_ERROR_USER_ACCOUNT_ALREADY_EXISTS);
+        }
+
+        UserInfo userInfo;
+        try {
+            userInfo = createUserInternal(userName, userType, flags,
+                    UserHandle.USER_NULL, null);
+
+            if (userInfo == null) {
+                throw new ServiceSpecificException(UserManager.USER_OPERATION_ERROR_UNKNOWN);
+            }
+        } catch (UserManager.CheckedUserOperationException e) {
+            throw e.toServiceSpecificException();
+        }
+
+        if (userIcon != null) {
+            mLocalService.setUserIcon(userInfo.id, userIcon);
+        }
+
+        setSeedAccountDataNoChecks(userInfo.id, accountName, accountType, accountOptions, true);
+
+        return userInfo.getUserHandle();
+    }
+
     private UserInfo createUserInternal(@Nullable String name, @NonNull String userType,
             @UserInfoFlag int flags, @UserIdInt int parentId,
             @Nullable String[] disallowedPackages)
@@ -3680,7 +3736,7 @@
                     userInfo.creationTime = getCreationTime();
                     userInfo.partial = true;
                     userInfo.preCreated = preCreate;
-                    userInfo.lastLoggedInFingerprint = Build.FINGERPRINT;
+                    userInfo.lastLoggedInFingerprint = PackagePartitions.FINGERPRINT;
                     if (userTypeDetails.hasBadge() && parentId != UserHandle.USER_NULL) {
                         userInfo.profileBadge = getFreeProfileBadgeLU(parentId, userType);
                     }
@@ -4811,7 +4867,8 @@
         t.traceBegin("onBeforeStartUser-" + userId);
         final int userSerial = userInfo.serialNumber;
         // Migrate only if build fingerprints mismatch
-        boolean migrateAppsData = !Build.FINGERPRINT.equals(userInfo.lastLoggedInFingerprint);
+        boolean migrateAppsData = !PackagePartitions.FINGERPRINT.equals(
+                userInfo.lastLoggedInFingerprint);
         t.traceBegin("prepareUserData");
         mUserDataPreparer.prepareUserData(userId, userSerial, StorageManager.FLAG_STORAGE_DE);
         t.traceEnd();
@@ -4841,7 +4898,8 @@
         }
         final int userSerial = userInfo.serialNumber;
         // Migrate only if build fingerprints mismatch
-        boolean migrateAppsData = !Build.FINGERPRINT.equals(userInfo.lastLoggedInFingerprint);
+        boolean migrateAppsData = !PackagePartitions.FINGERPRINT.equals(
+                userInfo.lastLoggedInFingerprint);
 
         final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
         t.traceBegin("prepareUserData-" + userId);
@@ -4885,7 +4943,7 @@
         if (now > EPOCH_PLUS_30_YEARS) {
             userData.info.lastLoggedInTime = now;
         }
-        userData.info.lastLoggedInFingerprint = Build.FINGERPRINT;
+        userData.info.lastLoggedInFingerprint = PackagePartitions.FINGERPRINT;
         scheduleWriteUser(userData);
     }
 
@@ -4934,7 +4992,12 @@
     @Override
     public void setSeedAccountData(@UserIdInt int userId, String accountName, String accountType,
             PersistableBundle accountOptions, boolean persist) {
-        checkManageUsersPermission("Require MANAGE_USERS permission to set user seed data");
+        checkManageUsersPermission("set user seed account data");
+        setSeedAccountDataNoChecks(userId, accountName, accountType, accountOptions, persist);
+    }
+
+    private void setSeedAccountDataNoChecks(@UserIdInt int userId, String accountName,
+            String accountType, PersistableBundle accountOptions, boolean persist) {
         synchronized (mPackagesLock) {
             final UserData userData;
             synchronized (mUsersLock) {
@@ -4996,14 +5059,18 @@
     }
 
     @Override
-    public boolean someUserHasSeedAccount(String accountName, String accountType)
-            throws RemoteException {
-        checkManageUsersPermission("Cannot check seed account information");
+    public boolean someUserHasSeedAccount(String accountName, String accountType) {
+        checkManageUsersPermission("check seed account information");
+        return someUserHasSeedAccountNoChecks(accountName, accountType);
+    }
+
+    private boolean someUserHasSeedAccountNoChecks(String accountName, String accountType) {
         synchronized (mUsersLock) {
             final int userSize = mUsers.size();
             for (int i = 0; i < userSize; i++) {
                 final UserData data = mUsers.valueAt(i);
                 if (data.info.isInitialized()) continue;
+                if (mRemovingUserIds.get(data.info.id)) continue;
                 if (data.seedAccountName == null || !data.seedAccountName.equals(accountName)) {
                     continue;
                 }
@@ -5017,6 +5084,25 @@
     }
 
     @Override
+    public boolean someUserHasAccount(String accountName, String accountType) {
+        checkManageOrCreateUsersPermission("check seed account information");
+        return someUserHasAccountNoChecks(accountName, accountType);
+    }
+
+    private boolean someUserHasAccountNoChecks(
+            String accountName, String accountType) {
+        if (TextUtils.isEmpty(accountName) || TextUtils.isEmpty(accountType)) {
+            return false;
+        }
+
+        final Account account = new Account(accountName, accountType);
+
+        return Binder.withCleanCallingIdentity(() ->
+                AccountManager.get(mContext).someUserHasAccount(account)
+                        || someUserHasSeedAccountNoChecks(accountName, accountType));
+    }
+
+    @Override
     public void onShellCommand(FileDescriptor in, FileDescriptor out,
             FileDescriptor err, String[] args, ShellCallback callback,
             ResultReceiver resultReceiver) {
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 7f42374..328a55f 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -142,7 +142,9 @@
             UserManager.DISALLOW_MICROPHONE_TOGGLE,
             UserManager.DISALLOW_CAMERA_TOGGLE,
             UserManager.DISALLOW_CHANGE_WIFI_STATE,
-            UserManager.DISALLOW_WIFI_TETHERING
+            UserManager.DISALLOW_WIFI_TETHERING,
+            UserManager.DISALLOW_SHARING_ADMIN_CONFIGURED_WIFI
+
     });
 
     public static final Set<String> DEPRECATED_USER_RESTRICTIONS = Sets.newArraySet(
diff --git a/services/core/java/com/android/server/pm/VerificationParams.java b/services/core/java/com/android/server/pm/VerificationParams.java
index 4dbc5d5..6d68139 100644
--- a/services/core/java/com/android/server/pm/VerificationParams.java
+++ b/services/core/java/com/android/server/pm/VerificationParams.java
@@ -399,6 +399,8 @@
 
             verification.putExtra(PackageInstaller.EXTRA_DATA_LOADER_TYPE, mDataLoaderType);
 
+            verification.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId);
+
             populateInstallerExtras(verification);
 
             final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index 5820489..5371454 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -1043,10 +1043,12 @@
     public long deleteOptimizedFiles(ArtPackageInfo packageInfo) {
         long freedBytes = 0;
         boolean hadErrors = false;
+        final String packageName = packageInfo.getPackageName();
         for (String codePath : packageInfo.getCodePaths()) {
             for (String isa : packageInfo.getInstructionSets()) {
                 try {
-                    freedBytes += mInstaller.deleteOdex(codePath, isa, packageInfo.getOatDir());
+                    freedBytes += mInstaller.deleteOdex(packageName, codePath, isa,
+                            packageInfo.getOatDir());
                 } catch (InstallerException e) {
                     Log.e(TAG, "Failed deleting oat files for " + codePath, e);
                     hadErrors = true;
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index ece0a62b..e207ff1 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -702,6 +702,14 @@
                         DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, userId),
                 userId, CONTACTS_PERMISSIONS);
 
+        // Maps
+        if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE, 0)) {
+            grantPermissionsToSystemPackage(pm,
+                getDefaultSystemHandlerActivityPackageForCategory(pm,
+                        Intent.CATEGORY_APP_MAPS, userId),
+                userId, FOREGROUND_LOCATION_PERMISSIONS);
+        }
+
         // Email
         grantPermissionsToSystemPackage(pm,
                 getDefaultSystemHandlerActivityPackageForCategory(pm,
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 3855e65..a01c358 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -4205,7 +4205,7 @@
         // Make sure all dynamic permissions have been assigned to a package,
         // and make sure there are no dangling permissions.
         boolean permissionSourcePackageChanged = updatePermissionSourcePackage(changingPkgName,
-                changingPkg, callback);
+                callback);
 
         if (permissionTreesSourcePackageChanged | permissionSourcePackageChanged) {
             // Permission ownership has changed. This e.g. changes which packages can get signature
@@ -4244,22 +4244,12 @@
     /**
      * Update which app declares a permission.
      *
-     * <p>Possible parameter combinations
-     * <table>
-     *     <tr><th></th><th>packageName != null</th><th>packageName == null</th></tr>
-     *     <tr><th>pkg != null</th><td>package is updated</td><td>invalid</td></tr>
-     *     <tr><th>pkg == null</th><td>package is deleted</td><td>all packages are updated</td></tr>
-     * </table>
-     *
      * @param packageName The package that is updated, or {@code null} if all packages should be
      *                    updated
-     * @param pkg The package that is updated, or {@code null} if all packages should be updated or
-     *            package is deleted
      *
      * @return {@code true} if a permission source package might have changed
      */
     private boolean updatePermissionSourcePackage(@Nullable String packageName,
-            @Nullable AndroidPackage pkg,
             final @Nullable PermissionCallback callback) {
         // Always need update if packageName is null
         if (packageName == null) {
@@ -4289,6 +4279,7 @@
             }
         }
         if (needsUpdate != null) {
+            final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
             for (final Permission bp : needsUpdate) {
                 // If the target package is being uninstalled, we need to revoke this permission
                 // From all other packages
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index ea3ef650..f61b562 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -124,7 +124,6 @@
 import android.hardware.hdmi.HdmiPlaybackClient;
 import android.hardware.hdmi.HdmiPlaybackClient.OneTouchPlayCallback;
 import android.hardware.input.InputManagerInternal;
-import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.AudioManagerInternal;
 import android.media.AudioSystem;
@@ -149,6 +148,7 @@
 import android.os.Trace;
 import android.os.UEventObserver;
 import android.os.UserHandle;
+import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.provider.DeviceConfig;
@@ -330,10 +330,12 @@
     private static final String TALKBACK_LABEL = "TalkBack";
 
     private static final int POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS = 800;
-    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
-            .build();
+    private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES =
+            VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH);
+    private static final VibrationAttributes PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES =
+            VibrationAttributes.createForUsage(VibrationAttributes.USAGE_PHYSICAL_EMULATION);
+    private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
+            VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
 
     /**
      * Keyguard stuff
@@ -519,7 +521,6 @@
     private boolean mPendingKeyguardOccluded;
     private boolean mKeyguardOccludedChanged;
 
-    private ActivityTaskManagerInternal.SleepTokenAcquirer mScreenOffSleepTokenAcquirer;
     Intent mHomeIntent;
     Intent mCarDockIntent;
     Intent mDeskDockIntent;
@@ -951,7 +952,7 @@
             powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
         } else if (count == 3) {
             powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
-        } else if (interactive && !beganFromNonInteractive) {
+        } else if (count == 1 && interactive && !beganFromNonInteractive) {
             if (mSideFpsEventHandler.onSinglePressDetected(eventTime)) {
                 Slog.i(TAG, "Suppressing power key because the user is interacting with the "
                         + "fingerprint sensor");
@@ -1117,21 +1118,21 @@
                 break;
             case LONG_PRESS_POWER_GLOBAL_ACTIONS:
                 mPowerKeyHandled = true;
-                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
+                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
                         "Power - Long Press - Global Actions");
                 showGlobalActions();
                 break;
             case LONG_PRESS_POWER_SHUT_OFF:
             case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
                 mPowerKeyHandled = true;
-                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
+                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
                         "Power - Long Press - Shut Off");
                 sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
                 mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
                 break;
             case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST:
                 mPowerKeyHandled = true;
-                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
+                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
                         "Power - Long Press - Go To Voice Assist");
                 // Some devices allow the voice assistant intent during setup (and use that intent
                 // to launch something else, like Settings). So we explicitly allow that via the
@@ -1155,7 +1156,7 @@
                 break;
             case VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS:
                 mPowerKeyHandled = true;
-                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
+                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
                         "Power - Very Long Press - Show Global Actions");
                 showGlobalActions();
                 break;
@@ -1817,9 +1818,6 @@
                 new AccessibilityShortcutController(mContext, new Handler(), mCurrentUserId);
         mLogger = new MetricsLogger();
 
-        mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal
-                .createSleepTokenAcquirer("ScreenOff");
-
         Resources res = mContext.getResources();
         mWakeOnDpadKeyPress =
                 res.getBoolean(com.android.internal.R.bool.config_wakeOnDpadKeyPress);
@@ -2100,7 +2098,8 @@
                                 mPowerKeyHandled = true;
                                 break;
                             case POWER_VOLUME_UP_BEHAVIOR_GLOBAL_ACTIONS:
-                                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
+                                performHapticFeedback(
+                                        HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON, false,
                                         "Power + Volume Up - Global Actions");
                                 showGlobalActions();
                                 mPowerKeyHandled = true;
@@ -3479,13 +3478,23 @@
         if (!mSystemBooted) {
             // If we have not yet booted, don't let key events do anything.
             // Exception: Wake and power key events are forwarded to PowerManager to allow it to
-            // wake from quiescent mode during boot.
+            // wake from quiescent mode during boot. On these key events we also explicitly turn on
+            // the connected TV and switch HDMI input if we're a HDMI playback device.
+            boolean shouldTurnOnTv = false;
             if (down && (keyCode == KeyEvent.KEYCODE_POWER
                     || keyCode == KeyEvent.KEYCODE_TV_POWER)) {
                 wakeUpFromPowerKey(event.getDownTime());
+                shouldTurnOnTv = true;
             } else if (down && (isWakeKey || keyCode == KeyEvent.KEYCODE_WAKEUP)
                     && isWakeKeyWhenScreenOff(keyCode)) {
                 wakeUpFromWakeKey(event);
+                shouldTurnOnTv = true;
+            }
+            if (shouldTurnOnTv) {
+                final HdmiControl hdmiControl = getHdmiControl();
+                if (hdmiControl != null) {
+                    hdmiControl.turnOnTv();
+                }
             }
             return 0;
         }
@@ -4475,7 +4484,6 @@
         if (DEBUG_WAKEUP) Slog.i(TAG, "Display" + displayId + " turned off...");
 
         if (displayId == DEFAULT_DISPLAY) {
-            updateScreenOffSleepToken(true);
             mRequestedOrSleepingDefaultDisplay = false;
             mDefaultDisplayPolicy.screenTurnedOff();
             synchronized (mLock) {
@@ -4508,7 +4516,6 @@
         if (displayId == DEFAULT_DISPLAY) {
             Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "screenTurningOn",
                     0 /* cookie */);
-            updateScreenOffSleepToken(false);
             mDefaultDisplayPolicy.screenTurnedOn(screenOnListener);
             mBootAnimationDismissable = false;
 
@@ -5029,15 +5036,6 @@
         }
     }
 
-    // TODO (multidisplay): Support multiple displays in WindowManagerPolicy.
-    private void updateScreenOffSleepToken(boolean acquire) {
-        if (acquire) {
-            mScreenOffSleepTokenAcquirer.acquire(DEFAULT_DISPLAY);
-        } else {
-            mScreenOffSleepTokenAcquirer.release(DEFAULT_DISPLAY);
-        }
-    }
-
     /** {@inheritDoc} */
     @Override
     public void enableScreenAfterBoot() {
@@ -5283,7 +5281,7 @@
             return false;
         }
 
-        mVibrator.vibrate(uid, packageName, effect, reason, VIBRATION_ATTRIBUTES);
+        mVibrator.vibrate(uid, packageName, effect, reason, getVibrationAttributes(effectId));
         return true;
     }
 
@@ -5312,6 +5310,7 @@
             case HapticFeedbackConstants.GESTURE_START:
                 return VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
             case HapticFeedbackConstants.LONG_PRESS:
+            case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON:
             case HapticFeedbackConstants.EDGE_SQUEEZE:
                 return VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
             case HapticFeedbackConstants.REJECT:
@@ -5350,6 +5349,22 @@
         }
     }
 
+    private VibrationAttributes getVibrationAttributes(int effectId) {
+        switch (effectId) {
+            case HapticFeedbackConstants.EDGE_SQUEEZE:
+            case HapticFeedbackConstants.EDGE_RELEASE:
+                return PHYSICAL_EMULATION_VIBRATION_ATTRIBUTES;
+            case HapticFeedbackConstants.ASSISTANT_BUTTON:
+            case HapticFeedbackConstants.LONG_PRESS_POWER_BUTTON:
+            case HapticFeedbackConstants.ROTARY_SCROLL_TICK:
+            case HapticFeedbackConstants.ROTARY_SCROLL_ITEM_FOCUS:
+            case HapticFeedbackConstants.ROTARY_SCROLL_LIMIT:
+                return HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES;
+            default:
+                return TOUCH_VIBRATION_ATTRIBUTES;
+        }
+    }
+
     @Override
     public void keepScreenOnStartedLw() {
     }
diff --git a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
index b7fb6e5..0276b37 100644
--- a/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
+++ b/services/core/java/com/android/server/policy/SingleKeyGestureDetector.java
@@ -44,7 +44,7 @@
     private static final int MSG_KEY_VERY_LONG_PRESS = 1;
     private static final int MSG_KEY_DELAYED_PRESS = 2;
 
-    private volatile int mKeyPressCounter;
+    private int mKeyPressCounter;
     private boolean mBeganFromNonInteractive = false;
 
     private final ArrayList<SingleKeyRule> mRules = new ArrayList();
@@ -53,7 +53,6 @@
     // Key code of current key down event, reset when key up.
     private int mDownKeyCode = KeyEvent.KEYCODE_UNKNOWN;
     private volatile boolean mHandledByLongPress = false;
-    private volatile boolean mHandledByMultiPress = false;
     private final Handler mHandler;
     private long mLastDownTime = 0;
     private static final long MULTI_PRESS_TIMEOUT = ViewConfiguration.getMultiPressTimeout();
@@ -223,7 +222,6 @@
             reset();
         }
         mDownKeyCode = keyCode;
-        mLastDownTime = event.getDownTime();
 
         // Picks a new rule, return if no rule picked.
         if (mActiveRule == null) {
@@ -238,12 +236,21 @@
                     break;
                 }
             }
+            mLastDownTime = 0;
         }
         if (mActiveRule == null) {
             return;
         }
 
-        if (mKeyPressCounter == 0) {
+        final long keyDownInterval = event.getDownTime() - mLastDownTime;
+        mLastDownTime = event.getDownTime();
+        if (keyDownInterval >= MULTI_PRESS_TIMEOUT) {
+            mKeyPressCounter = 1;
+        } else {
+            mKeyPressCounter++;
+        }
+
+        if (mKeyPressCounter == 1) {
             if (mActiveRule.supportLongPress()) {
                 final Message msg = mHandler.obtainMessage(MSG_KEY_LONG_PRESS, keyCode, 0,
                         mActiveRule);
@@ -263,17 +270,16 @@
             mHandler.removeMessages(MSG_KEY_DELAYED_PRESS);
 
             // Trigger multi press immediately when reach max count.( > 1)
-            if (mKeyPressCounter == mActiveRule.getMaxMultiPressCount() - 1) {
+            if (mActiveRule.getMaxMultiPressCount() > 1
+                    && mKeyPressCounter == mActiveRule.getMaxMultiPressCount()) {
                 if (DEBUG) {
                     Log.i(TAG, "Trigger multi press " + mActiveRule.toString() + " for it"
-                            + " reached the max count " + (mKeyPressCounter + 1));
+                            + " reached the max count " + mKeyPressCounter);
                 }
                 final Message msg = mHandler.obtainMessage(MSG_KEY_DELAYED_PRESS, keyCode,
-                        mKeyPressCounter + 1, mActiveRule);
+                        mKeyPressCounter, mActiveRule);
                 msg.setAsynchronous(true);
                 mHandler.sendMessage(msg);
-                mHandledByMultiPress = true;
-                mKeyPressCounter = 0;
             }
         }
     }
@@ -286,10 +292,10 @@
             return false;
         }
 
-        if (mHandledByLongPress || mHandledByMultiPress) {
+        if (mHandledByLongPress) {
             mHandledByLongPress = false;
-            mHandledByMultiPress = false;
             mKeyPressCounter = 0;
+            mActiveRule = null;
             return true;
         }
 
@@ -303,16 +309,17 @@
                         1, mActiveRule);
                 msg.setAsynchronous(true);
                 mHandler.sendMessage(msg);
-                reset();
+                mActiveRule = null;
                 return true;
             }
 
             // This could be a multi-press.  Wait a little bit longer to confirm.
-            mKeyPressCounter++;
-            Message msg = mHandler.obtainMessage(MSG_KEY_DELAYED_PRESS, mActiveRule.mKeyCode,
-                    mKeyPressCounter, mActiveRule);
-            msg.setAsynchronous(true);
-            mHandler.sendMessageDelayed(msg, MULTI_PRESS_TIMEOUT);
+            if (mKeyPressCounter < mActiveRule.getMaxMultiPressCount()) {
+                Message msg = mHandler.obtainMessage(MSG_KEY_DELAYED_PRESS, mActiveRule.mKeyCode,
+                        mKeyPressCounter, mActiveRule);
+                msg.setAsynchronous(true);
+                mHandler.sendMessageDelayed(msg, MULTI_PRESS_TIMEOUT);
+            }
             return true;
         }
         reset();
@@ -342,7 +349,6 @@
         }
 
         mHandledByLongPress = false;
-        mHandledByMultiPress = false;
         mDownKeyCode = KeyEvent.KEYCODE_UNKNOWN;
     }
 
@@ -373,9 +379,6 @@
                 Log.wtf(TAG, "No active rule.");
                 return;
             }
-            // We count the press count when interceptKeyUp. Reset the counter here to prevent if
-            // the multi-press or press happened but the count is less than max multi-press count.
-            mKeyPressCounter = 0;
 
             final int keyCode = msg.arg1;
             final int pressCount = msg.arg2;
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 5ec2f83..4571cf3 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -27,7 +27,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL;
-import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
 import static android.view.WindowManager.LayoutParams.TYPE_DISPLAY_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -190,14 +189,6 @@
         String getOwningPackage();
 
         /**
-         * Retrieve the current LayoutParams of the window.
-         *
-         * @return WindowManager.LayoutParams The window's internal LayoutParams
-         *         instance.
-         */
-        public WindowManager.LayoutParams getAttrs();
-
-        /**
          * Retrieve the type of the top-level window.
          *
          * @return the base type of the parent window if attached or its own type otherwise
@@ -658,26 +649,6 @@
     public boolean isKeyguardHostWindow(WindowManager.LayoutParams attrs);
 
     /**
-     * @return whether {@param win} can be hidden by Keyguard
-     */
-    default boolean canBeHiddenByKeyguardLw(WindowState win) {
-        // Keyguard visibility of window from activities are determined over activity visibility.
-        if (win.getBaseType() == TYPE_BASE_APPLICATION) {
-            return false;
-        }
-        switch (win.getAttrs().type) {
-            case TYPE_NOTIFICATION_SHADE:
-            case TYPE_STATUS_BAR:
-            case TYPE_NAVIGATION_BAR:
-            case TYPE_WALLPAPER:
-                return false;
-            default:
-                // Hide only windows below the keyguard host window.
-                return getWindowLayerLw(win) < getWindowLayerFromTypeLw(TYPE_NOTIFICATION_SHADE);
-        }
-    }
-
-    /**
      * Create and return an animation to re-display a window that was force hidden by Keyguard.
      */
     public Animation createHiddenByKeyguardExit(boolean onWallpaper,
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index c91d8de..70a804b 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -24,8 +24,8 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.hardware.display.DisplayManagerInternal;
 import android.hardware.input.InputManagerInternal;
-import android.media.AudioAttributes;
 import android.media.AudioManager;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
@@ -41,6 +41,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.os.WorkSource;
@@ -109,9 +110,8 @@
     private static final VibrationEffect CHARGING_VIBRATION_EFFECT =
             VibrationEffect.createWaveform(CHARGING_VIBRATION_TIME, CHARGING_VIBRATION_AMPLITUDE,
                     -1);
-    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
-            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
-            .build();
+    private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
+            VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
 
     private final Object mLock = new Object();
 
@@ -129,6 +129,7 @@
     private final TrustManager mTrustManager;
     private final Vibrator mVibrator;
     private final WakeLockLog mWakeLockLog;
+    private final DisplayManagerInternal mDisplayManagerInternal;
 
     private final NotifierHandler mHandler;
     private final Intent mScreenOnIntent;
@@ -181,6 +182,7 @@
         mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
         mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
         mStatusBarManagerInternal = LocalServices.getService(StatusBarManagerInternal.class);
+        mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
         mTrustManager = mContext.getSystemService(TrustManager.class);
         mVibrator = mContext.getSystemService(Vibrator.class);
 
@@ -460,7 +462,10 @@
         synchronized (mLock) {
             if (mInteractive) {
                 // Waking up...
-                mHandler.post(() -> mPolicy.startedWakingUp(mInteractiveChangeReason));
+                mHandler.post(() -> {
+                    mPolicy.startedWakingUp(mInteractiveChangeReason);
+                    mDisplayManagerInternal.onEarlyInteractivityChange(true /*isInteractive*/);
+                });
 
                 // Send interactive broadcast.
                 mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
@@ -469,7 +474,10 @@
             } else {
                 // Going to sleep...
                 // Tell the policy that we started going to sleep.
-                mHandler.post(() -> mPolicy.startedGoingToSleep(mInteractiveChangeReason));
+                mHandler.post(() -> {
+                    mPolicy.startedGoingToSleep(mInteractiveChangeReason);
+                    mDisplayManagerInternal.onEarlyInteractivityChange(false /*isInteractive*/);
+                });
             }
         }
     }
@@ -799,7 +807,7 @@
         final boolean vibrate = Settings.Secure.getIntForUser(mContext.getContentResolver(),
                 Settings.Secure.CHARGING_VIBRATION_ENABLED, 1, userId) != 0;
         if (vibrate) {
-            mVibrator.vibrate(CHARGING_VIBRATION_EFFECT, VIBRATION_ATTRIBUTES);
+            mVibrator.vibrate(CHARGING_VIBRATION_EFFECT, HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES);
         }
 
         // play sound
diff --git a/services/core/java/com/android/server/security/AttestationVerificationManagerService.java b/services/core/java/com/android/server/security/AttestationVerificationManagerService.java
new file mode 100644
index 0000000..f519ced
--- /dev/null
+++ b/services/core/java/com/android/server/security/AttestationVerificationManagerService.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 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.security;
+
+import static android.security.attestationverification.AttestationVerificationManager.RESULT_UNKNOWN;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelDuration;
+import android.os.RemoteException;
+import android.security.attestationverification.AttestationProfile;
+import android.security.attestationverification.IAttestationVerificationManagerService;
+import android.security.attestationverification.IVerificationResult;
+import android.security.attestationverification.VerificationToken;
+import android.util.ExceptionUtils;
+import android.util.Slog;
+
+import com.android.internal.infra.AndroidFuture;
+import com.android.server.SystemService;
+
+/**
+ * A {@link SystemService} which provides functionality related to verifying attestations of
+ * (usually) remote computing environments.
+ *
+ * @hide
+ */
+public class AttestationVerificationManagerService extends SystemService {
+
+    private static final String TAG = "AVF";
+
+    public AttestationVerificationManagerService(final Context context) {
+        super(context);
+    }
+
+    private final IBinder mService = new IAttestationVerificationManagerService.Stub() {
+        @Override
+        public void verifyAttestation(
+                AttestationProfile profile,
+                int localBindingType,
+                Bundle requirements,
+                byte[] attestation,
+                AndroidFuture resultCallback) throws RemoteException {
+            try {
+                Slog.d(TAG, "verifyAttestation");
+                verifyAttestationForAllVerifiers(profile, localBindingType, requirements,
+                        attestation, resultCallback);
+            } catch (Throwable t) {
+                Slog.e(TAG, "failed to verify attestation", t);
+                throw ExceptionUtils.propagate(t, RemoteException.class);
+            }
+        }
+
+        @Override
+        public void verifyToken(VerificationToken token, ParcelDuration parcelDuration,
+                AndroidFuture resultCallback) throws RemoteException {
+            // TODO(b/201696614): Implement
+            resultCallback.complete(RESULT_UNKNOWN);
+        }
+    };
+
+    private void verifyAttestationForAllVerifiers(
+            AttestationProfile profile, int localBindingType, Bundle requirements,
+            byte[] attestation, AndroidFuture<IVerificationResult> resultCallback) {
+        // TODO(b/201696614): Implement
+        IVerificationResult result = new IVerificationResult();
+        result.resultCode = RESULT_UNKNOWN;
+        result.token = null;
+        resultCallback.complete(result);
+    }
+
+    @Override
+    public void onStart() {
+        Slog.d(TAG, "Started");
+        publishBinderService(Context.ATTESTATION_VERIFICATION_SERVICE, mService);
+    }
+}
diff --git a/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java b/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java
new file mode 100644
index 0000000..0d420a5
--- /dev/null
+++ b/services/core/java/com/android/server/stats/bootstrap/StatsBootstrapAtomService.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2021 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.stats.bootstrap;
+
+import android.content.Context;
+import android.os.IStatsBootstrapAtomService;
+import android.os.StatsBootstrapAtom;
+import android.os.StatsBootstrapAtomValue;
+import android.util.Slog;
+import android.util.StatsEvent;
+import android.util.StatsLog;
+
+import com.android.server.SystemService;
+
+/**
+ * Proxy service for logging pushed atoms to statsd
+ *
+ * @hide
+ */
+public class StatsBootstrapAtomService extends IStatsBootstrapAtomService.Stub {
+
+    private static final String TAG = "StatsBootstrapAtomService";
+    private static final boolean DEBUG = false;
+
+    @Override
+    public void reportBootstrapAtom(StatsBootstrapAtom atom) {
+        if (atom.atomId < 1 || atom.atomId >= 10000) {
+            Slog.e(TAG, "Atom ID " + atom.atomId + " is not a valid atom ID");
+            return;
+        }
+        StatsEvent.Builder builder = StatsEvent.newBuilder().setAtomId(atom.atomId);
+        for (StatsBootstrapAtomValue value : atom.values) {
+            switch (value.getTag()) {
+                case StatsBootstrapAtomValue.boolValue:
+                    builder.writeBoolean(value.getBoolValue());
+                    break;
+                case StatsBootstrapAtomValue.intValue:
+                    builder.writeInt(value.getIntValue());
+                    break;
+                case StatsBootstrapAtomValue.longValue:
+                    builder.writeLong(value.getLongValue());
+                    break;
+                case StatsBootstrapAtomValue.floatValue:
+                    builder.writeFloat(value.getFloatValue());
+                    break;
+                case StatsBootstrapAtomValue.stringValue:
+                    builder.writeString(value.getStringValue());
+                    break;
+                case StatsBootstrapAtomValue.bytesValue:
+                    builder.writeByteArray(value.getBytesValue());
+                    break;
+                default:
+                    Slog.e(TAG, "Unexpected value type " + value.getTag()
+                            + " when logging atom " + atom.atomId);
+                    return;
+
+            }
+        }
+        StatsLog.write(builder.usePooledBuffer().build());
+    }
+
+    /**
+     * Lifecycle and related code
+     */
+    public static final class Lifecycle extends SystemService {
+        private StatsBootstrapAtomService mStatsBootstrapAtomService;
+
+        public Lifecycle(Context context) {
+            super(context);
+        }
+
+        @Override
+        public void onStart() {
+            mStatsBootstrapAtomService = new StatsBootstrapAtomService();
+            try {
+                publishBinderService(Context.STATS_BOOTSTRAP_ATOM_SERVICE,
+                        mStatsBootstrapAtomService);
+                if (DEBUG) Slog.d(TAG, "Published " + Context.STATS_BOOTSTRAP_ATOM_SERVICE);
+            } catch (Exception e) {
+                Slog.e(TAG, "Failed to publishBinderService", e);
+            }
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 0394d4c..eb69ff7 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -56,6 +56,7 @@
 import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__GEO;
 import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__MANUAL;
 import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__TELEPHONY;
+import static com.android.internal.util.FrameworkStatsLog.TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__UNKNOWN;
 import static com.android.server.am.MemoryStatUtil.readMemoryStatFromFilesystem;
 import static com.android.server.stats.pull.IonMemoryUtil.readProcessSystemIonHeapSizesFromDebugfs;
 import static com.android.server.stats.pull.IonMemoryUtil.readSystemIonHeapSizeFromDebugfs;
@@ -63,6 +64,8 @@
 import static com.android.server.stats.pull.ProcfsMemoryUtil.readCmdlineFromProcfs;
 import static com.android.server.stats.pull.ProcfsMemoryUtil.readMemorySnapshotFromProcfs;
 
+import static libcore.io.IoUtils.closeQuietly;
+
 import static java.lang.Math.min;
 import static java.util.concurrent.TimeUnit.HOURS;
 import static java.util.concurrent.TimeUnit.MICROSECONDS;
@@ -93,8 +96,12 @@
 import android.content.pm.PermissionInfo;
 import android.content.pm.UserInfo;
 import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.display.DisplayManager;
 import android.hardware.face.FaceManager;
 import android.hardware.fingerprint.FingerprintManager;
+import android.media.AudioManager;
+import android.media.MediaDrm;
+import android.media.UnsupportedSchemeException;
 import android.net.ConnectivityManager;
 import android.net.INetworkStatsService;
 import android.net.INetworkStatsSession;
@@ -163,6 +170,7 @@
 import android.util.SparseArray;
 import android.util.StatsEvent;
 import android.util.proto.ProtoOutputStream;
+import android.view.Display;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.procstats.IProcessStats;
@@ -216,6 +224,7 @@
 import org.json.JSONException;
 import org.json.JSONObject;
 
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -743,6 +752,8 @@
                         return pullAccessibilityShortcutStatsLocked(atomTag, data);
                     case FrameworkStatsLog.ACCESSIBILITY_FLOATING_MENU_STATS:
                         return pullAccessibilityFloatingMenuStatsLocked(atomTag, data);
+                    case FrameworkStatsLog.MEDIA_CAPABILITIES:
+                        return pullMediaCapabilitiesStats(atomTag, data);
                     default:
                         throw new UnsupportedOperationException("Unknown tagId=" + atomTag);
                 }
@@ -940,6 +951,7 @@
         registerKeystoreCrashStats();
         registerAccessibilityShortcutStats();
         registerAccessibilityFloatingMenuStats();
+        registerMediaCapabilitiesStats();
     }
 
     private void initAndRegisterNetworkStatsPullers() {
@@ -3399,14 +3411,17 @@
             pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag,
                     metricsState.isTelephonyDetectionSupported(),
                     metricsState.isGeoDetectionSupported(),
-                    metricsState.isUserLocationEnabled(),
+                    metricsState.getUserLocationEnabledSetting(),
                     metricsState.getAutoDetectionEnabledSetting(),
                     metricsState.getGeoDetectionEnabledSetting(),
                     convertToMetricsDetectionMode(metricsState.getDetectionMode()),
                     metricsState.getDeviceTimeZoneIdOrdinal(),
-                    metricsState.getLatestManualSuggestionProtoBytes(),
-                    metricsState.getLatestTelephonySuggestionProtoBytes(),
-                    metricsState.getLatestGeolocationSuggestionProtoBytes()
+                    convertTimeZoneSuggestionToProtoBytes(
+                            metricsState.getLatestManualSuggestion()),
+                    convertTimeZoneSuggestionToProtoBytes(
+                            metricsState.getLatestTelephonySuggestion()),
+                    convertTimeZoneSuggestionToProtoBytes(
+                            metricsState.getLatestGeolocationSuggestion())
             ));
         } catch (RuntimeException e) {
             Slog.e(TAG, "Getting time zone detection state failed: ", e);
@@ -3417,7 +3432,8 @@
         return StatsManager.PULL_SUCCESS;
     }
 
-    private int convertToMetricsDetectionMode(int detectionMode) {
+    private static int convertToMetricsDetectionMode(
+            @MetricsTimeZoneDetectorState.DetectionMode int detectionMode) {
         switch (detectionMode) {
             case MetricsTimeZoneDetectorState.DETECTION_MODE_MANUAL:
                 return TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__MANUAL;
@@ -3426,10 +3442,38 @@
             case MetricsTimeZoneDetectorState.DETECTION_MODE_TELEPHONY:
                 return TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__TELEPHONY;
             default:
-                throw new IllegalArgumentException("" + detectionMode);
+                return TIME_ZONE_DETECTOR_STATE__DETECTION_MODE__UNKNOWN;
         }
     }
 
+    @Nullable
+    private static byte[] convertTimeZoneSuggestionToProtoBytes(
+            @Nullable MetricsTimeZoneDetectorState.MetricsTimeZoneSuggestion suggestion) {
+        if (suggestion == null) {
+            return null;
+        }
+
+        // We don't get access to the atoms.proto definition for nested proto fields, so we use
+        // an identically specified proto.
+        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        ProtoOutputStream protoOutputStream = new ProtoOutputStream(byteArrayOutputStream);
+        int typeProtoValue = suggestion.isCertain()
+                ? android.app.time.MetricsTimeZoneSuggestion.CERTAIN
+                : android.app.time.MetricsTimeZoneSuggestion.UNCERTAIN;
+        protoOutputStream.write(android.app.time.MetricsTimeZoneSuggestion.TYPE,
+                typeProtoValue);
+        if (suggestion.isCertain()) {
+            for (int zoneIdOrdinal : suggestion.getZoneIdOrdinals()) {
+                protoOutputStream.write(
+                        android.app.time.MetricsTimeZoneSuggestion.TIME_ZONE_ORDINALS,
+                        zoneIdOrdinal);
+            }
+        }
+        protoOutputStream.flush();
+        closeQuietly(byteArrayOutputStream);
+        return byteArrayOutputStream.toByteArray();
+    }
+
     private void registerExternalStorageInfo() {
         int tagId = FrameworkStatsLog.EXTERNAL_STORAGE_INFO;
         mStatsManager.setPullAtomCallback(
@@ -4188,6 +4232,16 @@
         );
     }
 
+    private void registerMediaCapabilitiesStats() {
+        int tagId = FrameworkStatsLog.MEDIA_CAPABILITIES;
+        mStatsManager.setPullAtomCallback(
+                tagId,
+                null, // use default PullAtomMetadata values
+                DIRECT_EXECUTOR,
+                mStatsCallbackImpl
+        );
+    }
+
     int parseKeystoreStorageStats(KeystoreAtom[] atoms, List<StatsEvent> pulledData) {
         for (KeystoreAtom atomWrapper : atoms) {
             if (atomWrapper.payload.getTag() != KeystoreAtomPayload.storageStats) {
@@ -4470,6 +4524,162 @@
         return StatsManager.PULL_SUCCESS;
     }
 
+    int pullMediaCapabilitiesStats(int atomTag, List<StatsEvent> pulledData) {
+        AudioManager audioManager = mContext.getSystemService(AudioManager.class);
+        if (audioManager == null) {
+            return StatsManager.PULL_SKIP;
+        }
+
+        // get the surround sound metrics information
+        Map<Integer, Boolean> surroundEncodingsMap = audioManager.getSurroundFormats();
+        byte[] surroundEncodings = toBytes(new ArrayList(surroundEncodingsMap.keySet()));
+        byte[] sinkSurroundEncodings = toBytes(audioManager.getReportedSurroundFormats());
+        List<Integer> disabledSurroundEncodingsList = new ArrayList<>();
+        List<Integer> enabledSurroundEncodingsList = new ArrayList<>();
+        for (int surroundEncoding:  surroundEncodingsMap.keySet()) {
+            if (!surroundEncodingsMap.get(surroundEncoding)) {
+                disabledSurroundEncodingsList.add(surroundEncoding);
+            } else {
+                enabledSurroundEncodingsList.add(surroundEncoding);
+            }
+        }
+        byte[] disabledSurroundEncodings = toBytes(disabledSurroundEncodingsList);
+        byte[] enabledSurroundEncodings = toBytes(enabledSurroundEncodingsList);
+        int surroundOutputMode = audioManager.getEncodedSurroundMode();
+
+        DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+        Display display = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        // get the display capabilities metrics information
+        Display.HdrCapabilities hdrCapabilities = display.getHdrCapabilities();
+        byte[] sinkHdrFormats = new byte[]{};
+        if (hdrCapabilities != null) {
+            sinkHdrFormats = toBytes(hdrCapabilities.getSupportedHdrTypes());
+        }
+        byte[] sinkDisplayModes = toBytes(display.getSupportedModes());
+        int hdcpLevel = -1;
+        List<UUID> uuids = MediaDrm.getSupportedCryptoSchemes();
+        try {
+            if (!uuids.isEmpty()) {
+                MediaDrm mediaDrm = new MediaDrm(uuids.get(0));
+                hdcpLevel = mediaDrm.getConnectedHdcpLevel();
+            }
+        } catch (UnsupportedSchemeException exception) {
+            Slog.e(TAG, "pulling hdcp level failed.", exception);
+            hdcpLevel = -1;
+        }
+
+        // get the display settings metrics information
+        int matchContentFrameRateUserPreference =
+                displayManager.getMatchContentFrameRateUserPreference();
+        byte[] userDisabledHdrTypes = toBytes(displayManager.getUserDisabledHdrTypes());
+        Display.Mode userPreferredDisplayMode = displayManager.getUserPreferredDisplayMode();
+        int userPreferredWidth = userPreferredDisplayMode != null
+                ? userPreferredDisplayMode.getPhysicalWidth() : -1;
+        int userPreferredHeight = userPreferredDisplayMode != null
+                ? userPreferredDisplayMode.getPhysicalHeight() : -1;
+        float userPreferredRefreshRate = userPreferredDisplayMode != null
+                ? userPreferredDisplayMode.getRefreshRate() : 0.0f;
+        boolean hasUserDisabledAllm = false;
+        try {
+            hasUserDisabledAllm = Settings.Secure.getIntForUser(
+                    mContext.getContentResolver(),
+                    Settings.Secure.MINIMAL_POST_PROCESSING_ALLOWED,
+                    1) == 0;
+        } catch (Settings.SettingNotFoundException exception) {
+            Slog.e(
+                    TAG, "unable to find setting for MINIMAL_POST_PROCESSING_ALLOWED.",
+                    exception);
+            hasUserDisabledAllm = false;
+        }
+
+        pulledData.add(
+                FrameworkStatsLog.buildStatsEvent(
+                        atomTag, surroundEncodings, sinkSurroundEncodings,
+                        disabledSurroundEncodings, enabledSurroundEncodings, surroundOutputMode,
+                        sinkHdrFormats, sinkDisplayModes, hdcpLevel,
+                        matchContentFrameRateUserPreference, userDisabledHdrTypes,
+                        userPreferredWidth, userPreferredHeight, userPreferredRefreshRate,
+                        hasUserDisabledAllm));
+
+        return StatsManager.PULL_SUCCESS;
+    }
+
+    private byte[] toBytes(List<Integer> audioEncodings) {
+        ProtoOutputStream protoOutputStream = new ProtoOutputStream();
+        for (int audioEncoding : audioEncodings) {
+            protoOutputStream.write(
+                    ProtoOutputStream.FIELD_COUNT_REPEATED | ProtoOutputStream.FIELD_TYPE_ENUM | 1,
+                    audioEncoding);
+        }
+        return protoOutputStream.getBytes();
+    }
+
+    private byte[] toBytes(int[] array) {
+        ProtoOutputStream protoOutputStream = new ProtoOutputStream();
+        for (int element : array) {
+            protoOutputStream.write(
+                    ProtoOutputStream.FIELD_COUNT_REPEATED | ProtoOutputStream.FIELD_TYPE_ENUM | 1,
+                    element);
+        }
+        return protoOutputStream.getBytes();
+    }
+
+    private byte[] toBytes(Display.Mode[] displayModes) {
+        Map<Integer, Integer> modeGroupIds = createModeGroups(displayModes);
+        ProtoOutputStream protoOutputStream = new ProtoOutputStream();
+        for (Display.Mode element : displayModes) {
+            ProtoOutputStream protoOutputStreamMode = new ProtoOutputStream();
+            protoOutputStreamMode.write(
+                    ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 1,
+                    element.getPhysicalHeight());
+            protoOutputStreamMode.write(
+                    ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 2,
+                    element.getPhysicalWidth());
+            protoOutputStreamMode.write(
+                    ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_FLOAT | 3,
+                    element.getRefreshRate());
+            protoOutputStreamMode.write(
+                    ProtoOutputStream.FIELD_COUNT_SINGLE | ProtoOutputStream.FIELD_TYPE_INT32 | 4,
+                    modeGroupIds.get(element.getModeId()));
+            protoOutputStream.write(
+                    ProtoOutputStream.FIELD_COUNT_REPEATED
+                            | ProtoOutputStream.FIELD_TYPE_MESSAGE | 1,
+                    protoOutputStreamMode.getBytes());
+        }
+        return protoOutputStream.getBytes();
+    }
+
+    // Returns map modeId -> groupId such that all modes with the same group have alternative
+    // refresh rates
+    private Map<Integer, Integer> createModeGroups(Display.Mode[] supportedModes) {
+        Map<Integer, Integer> modeGroupIds = new ArrayMap<>();
+        int groupId = 1;
+        for (Display.Mode mode : supportedModes) {
+            if (modeGroupIds.containsKey(mode.getModeId())) {
+                continue;
+            }
+            modeGroupIds.put(mode.getModeId(), groupId);
+            for (float refreshRate : mode.getAlternativeRefreshRates()) {
+                int alternativeModeId = findModeId(supportedModes, mode.getPhysicalWidth(),
+                        mode.getPhysicalHeight(), refreshRate);
+                if (alternativeModeId != -1 && !modeGroupIds.containsKey(alternativeModeId)) {
+                    modeGroupIds.put(alternativeModeId, groupId);
+                }
+            }
+            groupId++;
+        }
+        return modeGroupIds;
+    }
+
+    private int findModeId(Display.Mode[] modes, int width, int height, float refreshRate) {
+        for (Display.Mode mode : modes) {
+            if (mode.matches(width, height, refreshRate)) {
+                return mode.getModeId();
+            }
+        }
+        return -1;
+    }
+
     /**
      * Counts how many accessibility services (including features) there are in the colon-separated
      * string list.
diff --git a/services/core/java/com/android/server/storage/AppFuseBridge.java b/services/core/java/com/android/server/storage/AppFuseBridge.java
index b00540f..2923148 100644
--- a/services/core/java/com/android/server/storage/AppFuseBridge.java
+++ b/services/core/java/com/android/server/storage/AppFuseBridge.java
@@ -24,7 +24,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.os.FuseUnavailableMountException;
 import com.android.internal.util.Preconditions;
-import com.android.server.NativeDaemonConnectorException;
+import com.android.server.AppFuseMountException;
 import libcore.io.IoUtils;
 import java.util.concurrent.CountDownLatch;
 
@@ -55,7 +55,7 @@
     }
 
     public ParcelFileDescriptor addBridge(MountScope mountScope)
-            throws FuseUnavailableMountException, NativeDaemonConnectorException {
+            throws FuseUnavailableMountException, AppFuseMountException {
         /*
         ** Dead Lock between Java lock (AppFuseBridge.java) and Native lock (FuseBridgeLoop.cc)
         **
@@ -112,7 +112,7 @@
         try {
             int flags = FileUtils.translateModePfdToPosix(mode);
             return scope.openFile(mountId, fileId, flags);
-        } catch (NativeDaemonConnectorException error) {
+        } catch (AppFuseMountException error) {
             throw new FuseUnavailableMountException(mountId);
         }
     }
@@ -160,9 +160,9 @@
             return mMountResult;
         }
 
-        public abstract ParcelFileDescriptor open() throws NativeDaemonConnectorException;
+        public abstract ParcelFileDescriptor open() throws AppFuseMountException;
         public abstract ParcelFileDescriptor openFile(int mountId, int fileId, int flags)
-                throws NativeDaemonConnectorException;
+                throws AppFuseMountException;
     }
 
     private native long native_new();
diff --git a/services/core/java/com/android/server/timedetector/ServerFlags.java b/services/core/java/com/android/server/timedetector/ServerFlags.java
index 477ebf6..d24a3df 100644
--- a/services/core/java/com/android/server/timedetector/ServerFlags.java
+++ b/services/core/java/com/android/server/timedetector/ServerFlags.java
@@ -65,6 +65,7 @@
             KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
             KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE,
             KEY_TIME_DETECTOR_ORIGIN_PRIORITIES_OVERRIDE,
+            KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED,
     })
     @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
     @Retention(RetentionPolicy.SOURCE)
@@ -139,6 +140,14 @@
             "location_time_zone_detection_setting_enabled_default";
 
     /**
+     * The key to control support for time zone detection falling back to telephony detection under
+     * certain circumstances.
+     */
+    public static final @DeviceConfigKey String
+            KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED =
+            "time_zone_detector_telephony_fallback_supported";
+
+    /**
      * The key to override the time detector origin priorities configuration. A comma-separated list
      * of strings that will be passed to {@link TimeDetectorStrategy#stringToOrigin(String)}.
      * All values must be recognized or the override value will be ignored.
diff --git a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
index 22814b3..65f077e 100644
--- a/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/ConfigurationInternal.java
@@ -39,21 +39,23 @@
 
     private final boolean mTelephonyDetectionSupported;
     private final boolean mGeoDetectionSupported;
-    private final boolean mAutoDetectionEnabled;
+    private final boolean mTelephonyFallbackSupported;
+    private final boolean mAutoDetectionEnabledSetting;
     private final @UserIdInt int mUserId;
     private final boolean mUserConfigAllowed;
-    private final boolean mLocationEnabled;
-    private final boolean mGeoDetectionEnabled;
+    private final boolean mLocationEnabledSetting;
+    private final boolean mGeoDetectionEnabledSetting;
 
     private ConfigurationInternal(Builder builder) {
         mTelephonyDetectionSupported = builder.mTelephonyDetectionSupported;
         mGeoDetectionSupported = builder.mGeoDetectionSupported;
-        mAutoDetectionEnabled = builder.mAutoDetectionEnabled;
+        mTelephonyFallbackSupported = builder.mTelephonyFallbackSupported;
+        mAutoDetectionEnabledSetting = builder.mAutoDetectionEnabledSetting;
 
         mUserId = builder.mUserId;
         mUserConfigAllowed = builder.mUserConfigAllowed;
-        mLocationEnabled = builder.mLocationEnabled;
-        mGeoDetectionEnabled = builder.mGeoDetectionEnabled;
+        mLocationEnabledSetting = builder.mLocationEnabledSetting;
+        mGeoDetectionEnabledSetting = builder.mGeoDetectionEnabledSetting;
     }
 
     /** Returns true if the device supports any form of auto time zone detection. */
@@ -71,9 +73,17 @@
         return mGeoDetectionSupported;
     }
 
+    /**
+     * Returns true if the device supports time zone detection falling back to telephony detection
+     * under certain circumstances.
+     */
+    public boolean isTelephonyFallbackSupported() {
+        return mTelephonyFallbackSupported;
+    }
+
     /** Returns the value of the auto time zone detection enabled setting. */
     public boolean getAutoDetectionEnabledSetting() {
-        return mAutoDetectionEnabled;
+        return mAutoDetectionEnabledSetting;
     }
 
     /**
@@ -81,7 +91,7 @@
      * from the raw setting value.
      */
     public boolean getAutoDetectionEnabledBehavior() {
-        return isAutoDetectionSupported() && mAutoDetectionEnabled;
+        return isAutoDetectionSupported() && mAutoDetectionEnabledSetting;
     }
 
     /** Returns the ID of the user this configuration is associated with. */
@@ -101,13 +111,13 @@
     }
 
     /** Returns true if user's location can be used generally. */
-    public boolean isLocationEnabled() {
-        return mLocationEnabled;
+    public boolean getLocationEnabledSetting() {
+        return mLocationEnabledSetting;
     }
 
     /** Returns the value of the geolocation time zone detection enabled setting. */
     public boolean getGeoDetectionEnabledSetting() {
-        return mGeoDetectionEnabled;
+        return mGeoDetectionEnabledSetting;
     }
 
     /**
@@ -117,7 +127,7 @@
     public boolean getGeoDetectionEnabledBehavior() {
         return getAutoDetectionEnabledBehavior()
                 && isGeoDetectionSupported()
-                && isLocationEnabled()
+                && getLocationEnabledSetting()
                 && getGeoDetectionEnabledSetting();
     }
 
@@ -154,7 +164,7 @@
         final int configureGeolocationDetectionEnabledCapability;
         if (!deviceHasLocationTimeZoneDetection) {
             configureGeolocationDetectionEnabledCapability = CAPABILITY_NOT_SUPPORTED;
-        } else if (!mAutoDetectionEnabled || !isLocationEnabled()) {
+        } else if (!mAutoDetectionEnabledSetting || !getLocationEnabledSetting()) {
             configureGeolocationDetectionEnabledCapability = CAPABILITY_NOT_APPLICABLE;
         } else {
             configureGeolocationDetectionEnabledCapability = CAPABILITY_POSSESSED;
@@ -195,10 +205,10 @@
     public ConfigurationInternal merge(TimeZoneConfiguration newConfiguration) {
         Builder builder = new Builder(this);
         if (newConfiguration.hasIsAutoDetectionEnabled()) {
-            builder.setAutoDetectionEnabled(newConfiguration.isAutoDetectionEnabled());
+            builder.setAutoDetectionEnabledSetting(newConfiguration.isAutoDetectionEnabled());
         }
         if (newConfiguration.hasIsGeoDetectionEnabled()) {
-            builder.setGeoDetectionEnabled(newConfiguration.isGeoDetectionEnabled());
+            builder.setGeoDetectionEnabledSetting(newConfiguration.isGeoDetectionEnabled());
         }
         return builder.build();
     }
@@ -216,16 +226,17 @@
                 && mUserConfigAllowed == that.mUserConfigAllowed
                 && mTelephonyDetectionSupported == that.mTelephonyDetectionSupported
                 && mGeoDetectionSupported == that.mGeoDetectionSupported
-                && mAutoDetectionEnabled == that.mAutoDetectionEnabled
-                && mLocationEnabled == that.mLocationEnabled
-                && mGeoDetectionEnabled == that.mGeoDetectionEnabled;
+                && mTelephonyFallbackSupported == that.mTelephonyFallbackSupported
+                && mAutoDetectionEnabledSetting == that.mAutoDetectionEnabledSetting
+                && mLocationEnabledSetting == that.mLocationEnabledSetting
+                && mGeoDetectionEnabledSetting == that.mGeoDetectionEnabledSetting;
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(mUserId, mUserConfigAllowed, mTelephonyDetectionSupported,
-                mGeoDetectionSupported, mAutoDetectionEnabled, mLocationEnabled,
-                mGeoDetectionEnabled);
+                mGeoDetectionSupported, mTelephonyFallbackSupported, mAutoDetectionEnabledSetting,
+                mLocationEnabledSetting, mGeoDetectionEnabledSetting);
     }
 
     @Override
@@ -235,9 +246,10 @@
                 + ", mUserConfigAllowed=" + mUserConfigAllowed
                 + ", mTelephonyDetectionSupported=" + mTelephonyDetectionSupported
                 + ", mGeoDetectionSupported=" + mGeoDetectionSupported
-                + ", mAutoDetectionEnabled=" + mAutoDetectionEnabled
-                + ", mLocationEnabled=" + mLocationEnabled
-                + ", mGeoDetectionEnabled=" + mGeoDetectionEnabled
+                + ", mTelephonyFallbackSupported=" + mTelephonyFallbackSupported
+                + ", mAutoDetectionEnabledSetting=" + mAutoDetectionEnabledSetting
+                + ", mLocationEnabledSetting=" + mLocationEnabledSetting
+                + ", mGeoDetectionEnabledSetting=" + mGeoDetectionEnabledSetting
                 + '}';
     }
 
@@ -251,9 +263,10 @@
         private boolean mUserConfigAllowed;
         private boolean mTelephonyDetectionSupported;
         private boolean mGeoDetectionSupported;
-        private boolean mAutoDetectionEnabled;
-        private boolean mLocationEnabled;
-        private boolean mGeoDetectionEnabled;
+        private boolean mTelephonyFallbackSupported;
+        private boolean mAutoDetectionEnabledSetting;
+        private boolean mLocationEnabledSetting;
+        private boolean mGeoDetectionEnabledSetting;
 
         /**
          * Creates a new Builder with only the userId set.
@@ -269,10 +282,11 @@
             this.mUserId = toCopy.mUserId;
             this.mUserConfigAllowed = toCopy.mUserConfigAllowed;
             this.mTelephonyDetectionSupported = toCopy.mTelephonyDetectionSupported;
+            this.mTelephonyFallbackSupported = toCopy.mTelephonyFallbackSupported;
             this.mGeoDetectionSupported = toCopy.mGeoDetectionSupported;
-            this.mAutoDetectionEnabled = toCopy.mAutoDetectionEnabled;
-            this.mLocationEnabled = toCopy.mLocationEnabled;
-            this.mGeoDetectionEnabled = toCopy.mGeoDetectionEnabled;
+            this.mAutoDetectionEnabledSetting = toCopy.mAutoDetectionEnabledSetting;
+            this.mLocationEnabledSetting = toCopy.mLocationEnabledSetting;
+            this.mGeoDetectionEnabledSetting = toCopy.mGeoDetectionEnabledSetting;
         }
 
         /**
@@ -300,26 +314,35 @@
         }
 
         /**
+         * Sets whether time zone detection supports falling back to telephony detection under
+         * certain circumstances.
+         */
+        public Builder setTelephonyFallbackSupported(boolean supported) {
+            mTelephonyFallbackSupported = supported;
+            return this;
+        }
+
+        /**
          * Sets the value of the automatic time zone detection enabled setting for this device.
          */
-        public Builder setAutoDetectionEnabled(boolean enabled) {
-            mAutoDetectionEnabled = enabled;
+        public Builder setAutoDetectionEnabledSetting(boolean enabled) {
+            mAutoDetectionEnabledSetting = enabled;
             return this;
         }
 
         /**
          * Sets the value of the location mode setting for this user.
          */
-        public Builder setLocationEnabled(boolean enabled) {
-            mLocationEnabled = enabled;
+        public Builder setLocationEnabledSetting(boolean enabled) {
+            mLocationEnabledSetting = enabled;
             return this;
         }
 
         /**
          * Sets the value of the geolocation time zone detection setting for this user.
          */
-        public Builder setGeoDetectionEnabled(boolean enabled) {
-            mGeoDetectionEnabled = enabled;
+        public Builder setGeoDetectionEnabledSetting(boolean enabled) {
+            mGeoDetectionEnabledSetting = enabled;
             return this;
         }
 
diff --git a/services/core/java/com/android/server/timezonedetector/DeviceActivityMonitor.java b/services/core/java/com/android/server/timezonedetector/DeviceActivityMonitor.java
new file mode 100644
index 0000000..62092ec
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/DeviceActivityMonitor.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2021 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.timezonedetector;
+
+import android.annotation.NonNull;
+
+/**
+ * The interface for the class that is responsible for detecting device activities relevant to
+ * time zone detection. This interface exists to decouple parts of the time zone detector from each
+ * other and to enable easier testing.
+ *
+ * @hide
+ */
+interface DeviceActivityMonitor extends Dumpable {
+
+    /** Adds a listener. */
+    void addListener(@NonNull Listener listener);
+
+    /**
+     * A listener for device activities. See {@link DeviceActivityMonitor#addListener(Listener)}.
+     */
+    interface Listener {
+        /** A flight has completed. */
+        void onFlightComplete();
+    }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/DeviceActivityMonitorImpl.java b/services/core/java/com/android/server/timezonedetector/DeviceActivityMonitorImpl.java
new file mode 100644
index 0000000..8c9bd3b
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/DeviceActivityMonitorImpl.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 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.timezonedetector;
+
+import android.annotation.NonNull;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.os.Handler;
+import android.provider.Settings;
+import android.util.IndentingPrintWriter;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * The real implementation of {@link DeviceActivityMonitor}.
+ */
+class DeviceActivityMonitorImpl implements DeviceActivityMonitor {
+
+    private static final String LOG_TAG = TimeZoneDetectorService.TAG;
+    private static final boolean DBG = TimeZoneDetectorService.DBG;
+
+    static DeviceActivityMonitor create(@NonNull Context context, @NonNull Handler handler) {
+        return new DeviceActivityMonitorImpl(context, handler);
+    }
+
+    @GuardedBy("this")
+    @NonNull
+    private final List<Listener> mListeners = new ArrayList<>();
+
+    private DeviceActivityMonitorImpl(@NonNull Context context, @NonNull Handler handler) {
+        // The way this "detects" a flight concluding is by the user explicitly turning off airplane
+        // mode. Smarter heuristics would be nice.
+        ContentResolver contentResolver = context.getContentResolver();
+        ContentObserver airplaneModeObserver = new ContentObserver(handler) {
+            @Override
+            public void onChange(boolean unused) {
+                try {
+                    int state = Settings.Global.getInt(
+                            contentResolver, Settings.Global.AIRPLANE_MODE_ON);
+                    if (state == 0) {
+                        notifyFlightComplete();
+                    }
+                } catch (Settings.SettingNotFoundException e) {
+                    Slog.e(LOG_TAG, "Unable to read airplane mode state", e);
+                }
+            }
+        };
+        contentResolver.registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON),
+                true /* notifyForDescendants */,
+                airplaneModeObserver);
+    }
+
+    @Override
+    public synchronized void addListener(Listener listener) {
+        Objects.requireNonNull(listener);
+        mListeners.add(listener);
+    }
+
+    private synchronized void notifyFlightComplete() {
+        if (DBG) {
+            Slog.d(LOG_TAG, "notifyFlightComplete");
+        }
+
+        for (Listener listener : mListeners) {
+            listener.onFlightComplete();
+        }
+    }
+
+    @Override
+    public void dump(IndentingPrintWriter pw, String[] args) {
+        // No-op right now: no state to dump.
+    }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/Dumpable.java b/services/core/java/com/android/server/timezonedetector/Dumpable.java
index 5603c38..1dd9637 100644
--- a/services/core/java/com/android/server/timezonedetector/Dumpable.java
+++ b/services/core/java/com/android/server/timezonedetector/Dumpable.java
@@ -24,18 +24,4 @@
 
     /** Dump internal state. */
     void dump(@NonNull IndentingPrintWriter pw, @Nullable String[] args);
-
-    /**
-     * An interface that can be used expose when one component allows another to be registered so
-     * that it is dumped at the same time.
-     */
-    interface Container {
-
-        /**
-         * Registers the supplied {@link Dumpable}. When the implementation is dumped
-         * {@link Dumpable#dump(IndentingPrintWriter, String[])} should be called on the
-         * {@code dumpable}.
-         */
-        void addDumpable(@NonNull Dumpable dumpable);
-    }
 }
diff --git a/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java b/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
index b84f8a8..0ec8826c 100644
--- a/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/EnvironmentImpl.java
@@ -16,132 +16,46 @@
 
 package com.android.server.timezonedetector;
 
-import static android.content.Intent.ACTION_USER_SWITCHED;
-
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.annotation.UserIdInt;
-import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
-import android.app.time.TimeZoneConfiguration;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.database.ContentObserver;
-import android.location.LocationManager;
 import android.os.Handler;
+import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.Settings;
-import android.util.Slog;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.server.LocalServices;
 
 import java.util.Objects;
-import java.util.Optional;
 
 /**
  * The real implementation of {@link TimeZoneDetectorStrategyImpl.Environment}.
  */
 final class EnvironmentImpl implements TimeZoneDetectorStrategyImpl.Environment {
 
-    private static final String LOG_TAG = TimeZoneDetectorService.TAG;
     private static final String TIMEZONE_PROPERTY = "persist.sys.timezone";
 
     @NonNull private final Context mContext;
     @NonNull private final Handler mHandler;
-    @NonNull private final ContentResolver mCr;
-    @NonNull private final UserManager mUserManager;
     @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
-    @NonNull private final LocationManager mLocationManager;
-
-    // @NonNull after setConfigChangeListener() is called.
-    @GuardedBy("this")
-    private ConfigurationChangeListener mConfigChangeListener;
 
     EnvironmentImpl(@NonNull Context context, @NonNull Handler handler,
             @NonNull ServiceConfigAccessor serviceConfigAccessor) {
         mContext = Objects.requireNonNull(context);
         mHandler = Objects.requireNonNull(handler);
-        mCr = context.getContentResolver();
-        mUserManager = context.getSystemService(UserManager.class);
-        mLocationManager = context.getSystemService(LocationManager.class);
         mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
-
-        // Wire up the config change listeners. All invocations are performed on the mHandler
-        // thread.
-
-        // Listen for the user changing / the user's location mode changing.
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(ACTION_USER_SWITCHED);
-        filter.addAction(LocationManager.MODE_CHANGED_ACTION);
-        mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                handleConfigChangeOnHandlerThread();
-            }
-        }, filter, null, mHandler);
-
-        // Add async callbacks for global settings being changed.
-        ContentResolver contentResolver = mContext.getContentResolver();
-        contentResolver.registerContentObserver(
-                Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true,
-                new ContentObserver(mHandler) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        handleConfigChangeOnHandlerThread();
-                    }
-                });
-
-        // Add async callbacks for user scoped location settings being changed.
-        contentResolver.registerContentObserver(
-                Settings.Secure.getUriFor(Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED),
-                true,
-                new ContentObserver(mHandler) {
-                    @Override
-                    public void onChange(boolean selfChange) {
-                        handleConfigChangeOnHandlerThread();
-                    }
-                }, UserHandle.USER_ALL);
-    }
-
-    private void handleConfigChangeOnHandlerThread() {
-        synchronized (this) {
-            if (mConfigChangeListener == null) {
-                Slog.wtf(LOG_TAG, "mConfigChangeListener is unexpectedly null");
-            }
-            mConfigChangeListener.onChange();
-        }
     }
 
     @Override
-    public void setConfigChangeListener(@NonNull ConfigurationChangeListener listener) {
-        synchronized (this) {
-            mConfigChangeListener = Objects.requireNonNull(listener);
-        }
+    public void setConfigurationInternalChangeListener(
+            @NonNull ConfigurationChangeListener listener) {
+        ConfigurationChangeListener configurationChangeListener =
+                () -> mHandler.post(listener::onChange);
+        mServiceConfigAccessor.addConfigurationInternalChangeListener(configurationChangeListener);
     }
 
     @Override
-    public ConfigurationInternal getConfigurationInternal(@UserIdInt int userId) {
-        return new ConfigurationInternal.Builder(userId)
-                .setTelephonyDetectionFeatureSupported(
-                        mServiceConfigAccessor.isTelephonyTimeZoneDetectionFeatureSupported())
-                .setGeoDetectionFeatureSupported(
-                        mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupported())
-                .setAutoDetectionEnabled(isAutoDetectionEnabled())
-                .setUserConfigAllowed(isUserConfigAllowed(userId))
-                .setLocationEnabled(isLocationEnabled(userId))
-                .setGeoDetectionEnabled(isGeoDetectionEnabled(userId))
-                .build();
-    }
-
-    @Override
-    public @UserIdInt int getCurrentUserId() {
-        return LocalServices.getService(ActivityManagerInternal.class).getCurrentUserId();
+    public ConfigurationInternal getCurrentUserConfigurationInternal() {
+        return mServiceConfigAccessor.getCurrentUserConfigurationInternal();
     }
 
     @Override
@@ -169,76 +83,7 @@
     }
 
     @Override
-    public void storeConfiguration(@UserIdInt int userId, TimeZoneConfiguration configuration) {
-        Objects.requireNonNull(configuration);
-
-        // Avoid writing the auto detection enabled setting for devices that do not support auto
-        // time zone detection: if we wrote it down then we'd set the value explicitly, which would
-        // prevent detecting "default" later. That might influence what happens on later releases
-        // that support new types of auto detection on the same hardware.
-        if (mServiceConfigAccessor.isAutoDetectionFeatureSupported()) {
-            final boolean autoDetectionEnabled = configuration.isAutoDetectionEnabled();
-            setAutoDetectionEnabledIfRequired(autoDetectionEnabled);
-
-            // Avoid writing the geo detection enabled setting for devices with settings that
-            // are currently overridden by server flags: otherwise we might overwrite a droidfood
-            // user's real setting permanently.
-            // Also avoid writing the geo detection enabled setting for devices that do not support
-            // geo time zone detection: if we wrote it down then we'd set the value explicitly,
-            // which would prevent detecting "default" later. That might influence what happens on
-            // later releases that start to support geo detection on the same hardware.
-            if (!mServiceConfigAccessor.getGeoDetectionSettingEnabledOverride().isPresent()
-                    && mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupported()) {
-                final boolean geoTzDetectionEnabled = configuration.isGeoDetectionEnabled();
-                setGeoDetectionEnabledIfRequired(userId, geoTzDetectionEnabled);
-            }
-        }
-    }
-
-    private boolean isUserConfigAllowed(@UserIdInt int userId) {
-        UserHandle userHandle = UserHandle.of(userId);
-        return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_DATE_TIME, userHandle);
-    }
-
-    private boolean isAutoDetectionEnabled() {
-        return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE, 1 /* default */) > 0;
-    }
-
-    private void setAutoDetectionEnabledIfRequired(boolean enabled) {
-        // This check is racey, but the whole settings update process is racey. This check prevents
-        // a ConfigurationChangeListener callback triggering due to ContentObserver's still
-        // triggering *sometimes* for no-op updates. Because callbacks are async this is necessary
-        // for stable behavior during tests.
-        if (isAutoDetectionEnabled() != enabled) {
-            Settings.Global.putInt(mCr, Settings.Global.AUTO_TIME_ZONE, enabled ? 1 : 0);
-        }
-    }
-
-    private boolean isLocationEnabled(@UserIdInt int userId) {
-        return mLocationManager.isLocationEnabledForUser(UserHandle.of(userId));
-    }
-
-    private boolean isGeoDetectionEnabled(@UserIdInt int userId) {
-        // We may never use this, but it gives us a way to force location-based time zone detection
-        // on/off for testers (but only where their other settings would allow them to turn it on
-        // for themselves).
-        Optional<Boolean> override = mServiceConfigAccessor.getGeoDetectionSettingEnabledOverride();
-        if (override.isPresent()) {
-            return override.get();
-        }
-
-        final boolean geoDetectionEnabledByDefault =
-                mServiceConfigAccessor.isGeoDetectionEnabledForUsersByDefault();
-        return Settings.Secure.getIntForUser(mCr,
-                Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED,
-                (geoDetectionEnabledByDefault ? 1 : 0) /* defaultValue */, userId) != 0;
-    }
-
-    private void setGeoDetectionEnabledIfRequired(@UserIdInt int userId, boolean enabled) {
-        // See comment in setAutoDetectionEnabledIfRequired. http://b/171953500
-        if (isGeoDetectionEnabled(userId) != enabled) {
-            Settings.Secure.putIntForUser(mCr, Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED,
-                    enabled ? 1 : 0, userId);
-        }
+    public @ElapsedRealtimeLong long elapsedRealtimeMillis() {
+        return SystemClock.elapsedRealtime();
     }
 }
diff --git a/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java b/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java
index 3b32549..f4a6ef0 100644
--- a/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java
+++ b/services/core/java/com/android/server/timezonedetector/GeolocationTimeZoneSuggestion.java
@@ -39,12 +39,11 @@
  * <ul>
  *     <li>{@code effectiveFromElapsedMillis}: The time according to the elapsed realtime clock
  *     after which the suggestion should be considered in effect. For example, when a location fix
- *     used to establish the time zone is old, then the suggestion
- *     {@code effectiveFromElapsedMillis} should reflect this and indicates the time zone that was
- *     detected / correct at that time. The time_zone_detector is only expected to use the latest
- *     suggestion it has received, and so later suggestions always counteract previous suggestions.
- *     The inclusion of this information means that the time_zone_detector can take into account
- *     ordering when comparing suggestions from different sources.
+ *     used to establish the time zone is old, then the suggestion's {@code
+ *     effectiveFromElapsedMillis} should reflect this and indicates the time zone that was
+ *     detected / correct at that time. The inclusion of this information means that the
+ *     time_zone_detector <em>may</em> take this into account if comparing suggestions or signals
+ *     from different sources.
  *     <br />Note: Because the times can be back-dated, time_zone_detector can be sent a sequence of
  *     suggestions where the {@code effectiveFromElapsedMillis} of later suggestions is before
  *     the {@code effectiveFromElapsedMillis} of an earlier one.</li>
diff --git a/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java b/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java
index 9eb6a45..f156f8c 100644
--- a/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java
+++ b/services/core/java/com/android/server/timezonedetector/MetricsTimeZoneDetectorState.java
@@ -16,16 +16,12 @@
 
 package com.android.server.timezonedetector;
 
-import static libcore.io.IoUtils.closeQuietly;
-
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.timezonedetector.ManualTimeZoneSuggestion;
 import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
-import android.util.proto.ProtoOutputStream;
 
-import java.io.ByteArrayOutputStream;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -50,22 +46,17 @@
             value = { DETECTION_MODE_MANUAL, DETECTION_MODE_GEO, DETECTION_MODE_TELEPHONY})
     @Retention(RetentionPolicy.SOURCE)
     @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
-    @interface DetectionMode {};
+    public @interface DetectionMode {};
 
     public static final @DetectionMode int DETECTION_MODE_MANUAL = 0;
     public static final @DetectionMode int DETECTION_MODE_GEO = 1;
     public static final @DetectionMode int DETECTION_MODE_TELEPHONY = 2;
 
-    @NonNull
-    private final ConfigurationInternal mConfigurationInternal;
-    @NonNull
+    @NonNull private final ConfigurationInternal mConfigurationInternal;
     private final int mDeviceTimeZoneIdOrdinal;
-    @Nullable
-    private final MetricsTimeZoneSuggestion mLatestManualSuggestion;
-    @Nullable
-    private final MetricsTimeZoneSuggestion mLatestTelephonySuggestion;
-    @Nullable
-    private final MetricsTimeZoneSuggestion mLatestGeolocationSuggestion;
+    @Nullable private final MetricsTimeZoneSuggestion mLatestManualSuggestion;
+    @Nullable private final MetricsTimeZoneSuggestion mLatestTelephonySuggestion;
+    @Nullable private final MetricsTimeZoneSuggestion mLatestGeolocationSuggestion;
 
     private MetricsTimeZoneDetectorState(
             @NonNull ConfigurationInternal configurationInternal,
@@ -94,16 +85,16 @@
 
         int deviceTimeZoneIdOrdinal =
                 tzIdOrdinalGenerator.ordinal(Objects.requireNonNull(deviceTimeZoneId));
-        MetricsTimeZoneSuggestion latestObfuscatedManualSuggestion =
+        MetricsTimeZoneSuggestion latestCanonicalManualSuggestion =
                 createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestManualSuggestion);
-        MetricsTimeZoneSuggestion latestObfuscatedTelephonySuggestion =
+        MetricsTimeZoneSuggestion latestCanonicalTelephonySuggestion =
                 createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestTelephonySuggestion);
-        MetricsTimeZoneSuggestion latestObfuscatedGeolocationSuggestion =
+        MetricsTimeZoneSuggestion latestCanonicalGeolocationSuggestion =
                 createMetricsTimeZoneSuggestion(tzIdOrdinalGenerator, latestGeolocationSuggestion);
 
         return new MetricsTimeZoneDetectorState(
-                configurationInternal, deviceTimeZoneIdOrdinal, latestObfuscatedManualSuggestion,
-                latestObfuscatedTelephonySuggestion, latestObfuscatedGeolocationSuggestion);
+                configurationInternal, deviceTimeZoneIdOrdinal, latestCanonicalManualSuggestion,
+                latestCanonicalTelephonySuggestion, latestCanonicalGeolocationSuggestion);
     }
 
     /** Returns true if the device supports telephony time zone detection. */
@@ -116,9 +107,14 @@
         return mConfigurationInternal.isGeoDetectionSupported();
     }
 
+    /** Returns true if the device supports telephony time zone detection fallback. */
+    public boolean isTelephonyTimeZoneFallbackSupported() {
+        return mConfigurationInternal.isTelephonyFallbackSupported();
+    }
+
     /** Returns true if user's location can be used generally. */
-    public boolean isUserLocationEnabled() {
-        return mConfigurationInternal.isLocationEnabled();
+    public boolean getUserLocationEnabledSetting() {
+        return mConfigurationInternal.getLocationEnabledSetting();
     }
 
     /** Returns the value of the geolocation time zone detection enabled setting. */
@@ -149,36 +145,32 @@
      * Returns the ordinal for the device's currently set time zone ID.
      * See {@link MetricsTimeZoneDetectorState} for information about ordinals.
      */
-    @NonNull
     public int getDeviceTimeZoneIdOrdinal() {
         return mDeviceTimeZoneIdOrdinal;
     }
 
     /**
-     * Returns bytes[] for a {@link MetricsTimeZoneSuggestion} for the last manual
-     * suggestion received.
+     * Returns a canonical form of the last manual suggestion received.
      */
     @Nullable
-    public byte[] getLatestManualSuggestionProtoBytes() {
-        return suggestionProtoBytes(mLatestManualSuggestion);
+    public MetricsTimeZoneSuggestion getLatestManualSuggestion() {
+        return mLatestManualSuggestion;
     }
 
     /**
-     * Returns bytes[] for a {@link MetricsTimeZoneSuggestion} for the last, best
-     * telephony suggestion received.
+     * Returns a canonical form of the last telephony suggestion received.
      */
     @Nullable
-    public byte[] getLatestTelephonySuggestionProtoBytes() {
-        return suggestionProtoBytes(mLatestTelephonySuggestion);
+    public MetricsTimeZoneSuggestion getLatestTelephonySuggestion() {
+        return mLatestTelephonySuggestion;
     }
 
     /**
-     * Returns bytes[] for a {@link MetricsTimeZoneSuggestion} for the last geolocation
-     * suggestion received.
+     * Returns a canonical form of last geolocation suggestion received.
      */
     @Nullable
-    public byte[] getLatestGeolocationSuggestionProtoBytes() {
-        return suggestionProtoBytes(mLatestGeolocationSuggestion);
+    public MetricsTimeZoneSuggestion getLatestGeolocationSuggestion() {
+        return mLatestGeolocationSuggestion;
     }
 
     @Override
@@ -214,14 +206,6 @@
                 + '}';
     }
 
-    private static byte[] suggestionProtoBytes(
-            @Nullable MetricsTimeZoneSuggestion suggestion) {
-        if (suggestion == null) {
-            return null;
-        }
-        return suggestion.toBytes();
-    }
-
     @Nullable
     private static MetricsTimeZoneSuggestion createMetricsTimeZoneSuggestion(
             @NonNull OrdinalGenerator<String> zoneIdOrdinalGenerator,
@@ -265,10 +249,11 @@
     }
 
     /**
-     * A Java class that closely matches the android.app.time.MetricsTimeZoneSuggestion
-     * proto definition.
+     * A Java class that represents a generic time zone suggestion, i.e. one that is independent of
+     * origin-specific information. This closely matches the metrics atoms.proto
+     * MetricsTimeZoneSuggestion proto definition.
      */
-    private static final class MetricsTimeZoneSuggestion {
+    public static final class MetricsTimeZoneSuggestion {
         @Nullable
         private final int[] mZoneIdOrdinals;
 
@@ -281,42 +266,21 @@
             return new MetricsTimeZoneSuggestion(null);
         }
 
-        public static MetricsTimeZoneSuggestion createCertain(
+        @NonNull
+        static MetricsTimeZoneSuggestion createCertain(
                 @NonNull int[] zoneIdOrdinals) {
             return new MetricsTimeZoneSuggestion(zoneIdOrdinals);
         }
 
-        boolean isCertain() {
+        public boolean isCertain() {
             return mZoneIdOrdinals != null;
         }
 
         @Nullable
-        int[] getZoneIdOrdinals() {
+        public int[] getZoneIdOrdinals() {
             return mZoneIdOrdinals;
         }
 
-        byte[] toBytes() {
-            // We don't get access to the atoms.proto definition for nested proto fields, so we use
-            // an identically specified proto.
-            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
-            ProtoOutputStream protoOutputStream = new ProtoOutputStream(byteArrayOutputStream);
-            int typeProtoValue = isCertain()
-                    ? android.app.time.MetricsTimeZoneSuggestion.CERTAIN
-                    : android.app.time.MetricsTimeZoneSuggestion.UNCERTAIN;
-            protoOutputStream.write(android.app.time.MetricsTimeZoneSuggestion.TYPE,
-                    typeProtoValue);
-            if (isCertain()) {
-                for (int zoneIdOrdinal : getZoneIdOrdinals()) {
-                    protoOutputStream.write(
-                            android.app.time.MetricsTimeZoneSuggestion.TIME_ZONE_ORDINALS,
-                            zoneIdOrdinal);
-                }
-            }
-            protoOutputStream.flush();
-            closeQuietly(byteArrayOutputStream);
-            return byteArrayOutputStream.toByteArray();
-        }
-
         @Override
         public boolean equals(Object o) {
             if (this == o) {
diff --git a/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java b/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java
index 4eb1b99..60068cb 100644
--- a/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java
+++ b/services/core/java/com/android/server/timezonedetector/ReferenceWithHistory.java
@@ -25,6 +25,7 @@
 
 import java.time.Duration;
 import java.util.ArrayDeque;
+import java.util.Iterator;
 
 /**
  * A class that behaves like the following definition, except it stores the history of values set
@@ -112,9 +113,11 @@
         if (mValues == null) {
             ipw.println("{Empty}");
         } else {
-            int i = mSetCount;
-            for (TimestampedValue<V> valueHolder : mValues) {
-                ipw.print(--i);
+            int i = mSetCount - mValues.size();
+            Iterator<TimestampedValue<V>> reverseIterator = mValues.descendingIterator();
+            while (reverseIterator.hasNext()) {
+                TimestampedValue<V> valueHolder = reverseIterator.next();
+                ipw.print(i++);
                 ipw.print("@");
                 ipw.print(Duration.ofMillis(valueHolder.getReferenceTimeMillis()).toString());
                 ipw.print(": ");
diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
index 20f4fa1..692b0cc 100644
--- a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
+++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessor.java
@@ -18,420 +18,221 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.StringDef;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.os.SystemProperties;
-import android.util.ArraySet;
-
-import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
-import com.android.server.timedetector.ServerFlags;
+import android.annotation.UserIdInt;
+import android.app.time.TimeZoneConfiguration;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.time.Duration;
-import java.util.Collections;
-import java.util.Objects;
 import java.util.Optional;
-import java.util.Set;
 
 /**
- * A singleton that provides access to service configuration for time zone detection. This hides how
- * configuration is split between static, compile-time config and dynamic, server-pushed flags. It
- * provides a rudimentary mechanism to signal when values have changed.
+ * An interface that provides access to service configuration for time zone detection. This hides
+ * how configuration is split between static, compile-time config, dynamic server-pushed flags and
+ * user settings. It provides listeners to signal when values that affect different components have
+ * changed.
  */
-public final class ServiceConfigAccessor {
+public interface ServiceConfigAccessor {
 
     @StringDef(prefix = "PROVIDER_MODE_",
-            value = { PROVIDER_MODE_DISABLED, PROVIDER_MODE_ENABLED})
+            value = { PROVIDER_MODE_DISABLED, PROVIDER_MODE_ENABLED })
     @Retention(RetentionPolicy.SOURCE)
     @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
-    @interface ProviderMode {}
+    @interface ProviderMode {
+    }
 
     /**
      * The "disabled" provider mode. For use with {@link #getPrimaryLocationTimeZoneProviderMode()}
      * and {@link #getSecondaryLocationTimeZoneProviderMode()}.
      */
-    public static final @ProviderMode String PROVIDER_MODE_DISABLED = "disabled";
+    @ProviderMode String PROVIDER_MODE_DISABLED = "disabled";
 
     /**
      * The "enabled" provider mode. For use with {@link #getPrimaryLocationTimeZoneProviderMode()}
      * and {@link #getSecondaryLocationTimeZoneProviderMode()}.
      */
-    public static final @ProviderMode String PROVIDER_MODE_ENABLED = "enabled";
+    @ProviderMode String PROVIDER_MODE_ENABLED = "enabled";
 
     /**
-     * Device config keys that affect the {@link TimeZoneDetectorService} service and {@link
-     * com.android.server.timezonedetector.location.LocationTimeZoneManagerService}.
+     * Adds a listener that will be invoked when {@link ConfigurationInternal} may have changed.
+     * The listener is invoked on the main thread.
      */
-    private static final Set<String> SERVER_FLAGS_KEYS_TO_WATCH = Collections.unmodifiableSet(
-            new ArraySet<>(new String[] {
-                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
-                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
-                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
-                    ServerFlags.KEY_PRIMARY_LTZP_MODE_OVERRIDE,
-                    ServerFlags.KEY_SECONDARY_LTZP_MODE_OVERRIDE,
-                    ServerFlags.KEY_LTZP_INITIALIZATION_TIMEOUT_MILLIS,
-                    ServerFlags.KEY_LTZP_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
-                    ServerFlags.KEY_LTZP_EVENT_FILTERING_AGE_THRESHOLD_MILLIS,
-                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS
-            }));
-
-    private static final Duration DEFAULT_LTZP_INITIALIZATION_TIMEOUT = Duration.ofMinutes(5);
-    private static final Duration DEFAULT_LTZP_INITIALIZATION_TIMEOUT_FUZZ = Duration.ofMinutes(1);
-    private static final Duration DEFAULT_LTZP_UNCERTAINTY_DELAY = Duration.ofMinutes(5);
-    private static final Duration DEFAULT_LTZP_EVENT_FILTER_AGE_THRESHOLD = Duration.ofMinutes(1);
-
-    private static final Object SLOCK = new Object();
-
-    /** The singleton instance. Initialized once in {@link #getInstance(Context)}. */
-    @GuardedBy("SLOCK")
-    @Nullable
-    private static ServiceConfigAccessor sInstance;
-
-    @NonNull private final Context mContext;
+    void addConfigurationInternalChangeListener(
+            @NonNull ConfigurationChangeListener listener);
 
     /**
-     * An ultimate "feature switch" for location-based time zone detection. If this is
-     * {@code false}, the device cannot support the feature without a config change or a reboot:
-     * This affects what services are started on boot to minimize expense when the feature is not
-     * wanted.
+     * Removes a listener previously added via {@link
+     * #addConfigurationInternalChangeListener(ConfigurationChangeListener)}.
      */
-    private final boolean mGeoDetectionFeatureSupportedInConfig;
-
-    @NonNull private final ServerFlags mServerFlags;
+    void removeConfigurationInternalChangeListener(
+            @NonNull ConfigurationChangeListener listener);
 
     /**
-     * The mode to use for the primary location time zone provider in a test. Setting this
-     * disables some permission checks.
-     * This state is volatile: it is never written to storage / never survives a reboot. This is to
-     * avoid a test provider accidentally being left configured on a device.
-     * See also {@link #resetVolatileTestConfig()}.
+     * Returns a snapshot of the {@link ConfigurationInternal} for the current user. This is only a
+     * snapshot so callers must use {@link
+     * #addConfigurationInternalChangeListener(ConfigurationChangeListener)} to be notified when it
+     * changes.
      */
-    @Nullable
-    private String mTestPrimaryLocationTimeZoneProviderMode;
+    @NonNull
+    ConfigurationInternal getCurrentUserConfigurationInternal();
 
     /**
-     * The package name to use for the primary location time zone provider in a test.
-     * This state is volatile: it is never written to storage / never survives a reboot. This is to
-     * avoid a test provider accidentally being left configured on a device.
-     * See also {@link #resetVolatileTestConfig()}.
-     */
-    @Nullable
-    private String mTestPrimaryLocationTimeZoneProviderPackageName;
-
-    /**
-     * See {@link #mTestPrimaryLocationTimeZoneProviderMode}; this is the equivalent for the
-     * secondary provider.
-     */
-    @Nullable
-    private String mTestSecondaryLocationTimeZoneProviderMode;
-
-    /**
-     * See {@link #mTestPrimaryLocationTimeZoneProviderPackageName}; this is the equivalent for the
-     * secondary provider.
-     */
-    @Nullable
-    private String mTestSecondaryLocationTimeZoneProviderPackageName;
-
-    /**
-     * Whether to record state changes for tests.
-     * This state is volatile: it is never written to storage / never survives a reboot. This is to
-     * avoid a test state accidentally being left configured on a device.
-     * See also {@link #resetVolatileTestConfig()}.
-     */
-    private boolean mRecordProviderStateChanges;
-
-    private ServiceConfigAccessor(@NonNull Context context) {
-        mContext = Objects.requireNonNull(context);
-
-        // The config value is expected to be the main feature flag. Platform developers can also
-        // force enable the feature using a persistent system property. Because system properties
-        // can change, this value is cached and only changes on reboot.
-        mGeoDetectionFeatureSupportedInConfig = context.getResources().getBoolean(
-                com.android.internal.R.bool.config_enableGeolocationTimeZoneDetection)
-                || SystemProperties.getBoolean(
-                "persist.sys.location_time_zone_detection_feature_supported", false);
-
-        mServerFlags = ServerFlags.getInstance(mContext);
-    }
-
-    /** Returns the singleton instance. */
-    public static ServiceConfigAccessor getInstance(Context context) {
-        synchronized (SLOCK) {
-            if (sInstance == null) {
-                sInstance = new ServiceConfigAccessor(context);
-            }
-            return sInstance;
-        }
-    }
-
-    /**
-     * Adds a listener that will be called when server flags related to this class change. The
-     * callbacks are delivered on the main looper thread.
+     * Updates the configuration properties that control a device's time zone behavior.
      *
-     * <p>Note: Only for use by long-lived objects. There is deliberately no associated remove
-     * method.
+     * <p>This method returns {@code true} if the configuration was changed,
+     * {@code false} otherwise.
      */
-    public void addListener(@NonNull ConfigurationChangeListener listener) {
-        mServerFlags.addListener(listener, SERVER_FLAGS_KEYS_TO_WATCH);
-    }
+    boolean updateConfiguration(@UserIdInt int userId,
+            @NonNull TimeZoneConfiguration requestedConfiguration);
 
-    /** Returns {@code true} if any form of automatic time zone detection is supported. */
-    public boolean isAutoDetectionFeatureSupported() {
-        return isTelephonyTimeZoneDetectionFeatureSupported()
-                || isGeoTimeZoneDetectionFeatureSupported();
-    }
+    /**
+     * Returns a snapshot of the configuration that controls time zone detector behavior for the
+     * specified user.
+     */
+    @NonNull
+    ConfigurationInternal getConfigurationInternal(@UserIdInt int userId);
+
+    /**
+     * Adds a listener that will be called when server flags related to location_time_zone_manager
+     * change. The callbacks are delivered on the main looper thread.
+     *
+     * <p>Note: Currently only for use by long-lived objects; there is no associated remove method.
+     */
+    void addLocationTimeZoneManagerConfigListener(
+            @NonNull ConfigurationChangeListener listener);
 
     /**
      * Returns {@code true} if the telephony-based time zone detection feature is supported on the
      * device.
      */
-    public boolean isTelephonyTimeZoneDetectionFeatureSupported() {
-        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
-    }
+    boolean isTelephonyTimeZoneDetectionFeatureSupported();
 
     /**
      * Returns {@code true} if the location-based time zone detection feature can be supported on
      * this device at all according to config. When {@code false}, implies that various other
-     * location-based settings will be turned off or rendered meaningless. Typically {@link
-     * #isGeoTimeZoneDetectionFeatureSupported()} should be used instead.
+     * location-based services and settings will be turned off or rendered meaningless.
+     *
+     * <p>This is the ultimate "feature switch" for location-based time zone detection. If this is
+     * {@code false}, the device cannot support the feature without a config change or a reboot:
+     * This affects what services are started on boot to minimize expense when the feature is not
+     * wanted.
+     *
+     * Typically {@link #isGeoTimeZoneDetectionFeatureSupported()} should be used except during
+     * boot.
      */
-    public boolean isGeoTimeZoneDetectionFeatureSupportedInConfig() {
-        return mGeoDetectionFeatureSupportedInConfig;
-    }
+    boolean isGeoTimeZoneDetectionFeatureSupportedInConfig();
 
     /**
      * Returns {@code true} if the location-based time zone detection feature is supported on the
      * device.
      */
-    public boolean isGeoTimeZoneDetectionFeatureSupported() {
-        // For the feature to be enabled it must:
-        // 1) Be turned on in config.
-        // 2) Not be turned off via a server flag.
-        // 3) There must be at least one location time zone provider enabled / configured.
-        return mGeoDetectionFeatureSupportedInConfig
-                && isGeoTimeZoneDetectionFeatureSupportedInternal()
-                && atLeastOneProviderIsEnabled();
-    }
-
-    private boolean atLeastOneProviderIsEnabled() {
-        return !(Objects.equals(getPrimaryLocationTimeZoneProviderMode(), PROVIDER_MODE_DISABLED)
-                && Objects.equals(getSecondaryLocationTimeZoneProviderMode(),
-                PROVIDER_MODE_DISABLED));
-    }
-
-    /**
-     * Returns {@code true} if the location-based time zone detection feature is not explicitly
-     * disabled by a server flag.
-     */
-    private boolean isGeoTimeZoneDetectionFeatureSupportedInternal() {
-        final boolean defaultEnabled = true;
-        return mServerFlags.getBoolean(
-                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
-                defaultEnabled);
-    }
+    boolean isGeoTimeZoneDetectionFeatureSupported();
 
     /** Returns the package name of the app hosting the primary location time zone provider. */
     @NonNull
-    public String getPrimaryLocationTimeZoneProviderPackageName() {
-        if (mTestPrimaryLocationTimeZoneProviderMode != null) {
-            // In test mode: use the test setting value.
-            return mTestPrimaryLocationTimeZoneProviderPackageName;
-        }
-        return mContext.getResources().getString(
-                R.string.config_primaryLocationTimeZoneProviderPackageName);
-    }
+    String getPrimaryLocationTimeZoneProviderPackageName();
 
     /**
      * Sets the package name of the app hosting the primary location time zone provider for tests.
      * Setting a {@code null} value means the provider is to be disabled.
      * The values are reset with {@link #resetVolatileTestConfig()}.
      */
-    public void setTestPrimaryLocationTimeZoneProviderPackageName(
-            @Nullable String testPrimaryLocationTimeZoneProviderPackageName) {
-        mTestPrimaryLocationTimeZoneProviderPackageName =
-                testPrimaryLocationTimeZoneProviderPackageName;
-        mTestPrimaryLocationTimeZoneProviderMode =
-                mTestPrimaryLocationTimeZoneProviderPackageName == null
-                        ? PROVIDER_MODE_DISABLED : PROVIDER_MODE_ENABLED;
-    }
+    void setTestPrimaryLocationTimeZoneProviderPackageName(
+            @Nullable String testPrimaryLocationTimeZoneProviderPackageName);
 
     /**
      * Returns {@code true} if the usual permission checks are to be bypassed for the primary
      * provider. Returns {@code true} only if {@link
      * #setTestPrimaryLocationTimeZoneProviderPackageName} has been called.
      */
-    public boolean isTestPrimaryLocationTimeZoneProvider() {
-        return mTestPrimaryLocationTimeZoneProviderMode != null;
-    }
+    boolean isTestPrimaryLocationTimeZoneProvider();
 
     /** Returns the package name of the app hosting the secondary location time zone provider. */
     @NonNull
-    public String getSecondaryLocationTimeZoneProviderPackageName() {
-        if (mTestSecondaryLocationTimeZoneProviderMode != null) {
-            // In test mode: use the test setting value.
-            return mTestSecondaryLocationTimeZoneProviderPackageName;
-        }
-        return mContext.getResources().getString(
-                R.string.config_secondaryLocationTimeZoneProviderPackageName);
-    }
+    String getSecondaryLocationTimeZoneProviderPackageName();
 
     /**
      * Sets the package name of the app hosting the secondary location time zone provider for tests.
      * Setting a {@code null} value means the provider is to be disabled.
      * The values are reset with {@link #resetVolatileTestConfig()}.
      */
-    public void setTestSecondaryLocationTimeZoneProviderPackageName(
-            @Nullable String testSecondaryLocationTimeZoneProviderPackageName) {
-        mTestSecondaryLocationTimeZoneProviderPackageName =
-                testSecondaryLocationTimeZoneProviderPackageName;
-        mTestSecondaryLocationTimeZoneProviderMode =
-                mTestSecondaryLocationTimeZoneProviderPackageName == null
-                        ? PROVIDER_MODE_DISABLED : PROVIDER_MODE_ENABLED;
-    }
+    void setTestSecondaryLocationTimeZoneProviderPackageName(
+            @Nullable String testSecondaryLocationTimeZoneProviderPackageName);
 
     /**
      * Returns {@code true} if the usual permission checks are to be bypassed for the secondary
      * provider. Returns {@code true} only if {@link
      * #setTestSecondaryLocationTimeZoneProviderPackageName} has been called.
      */
-    public boolean isTestSecondaryLocationTimeZoneProvider() {
-        return mTestSecondaryLocationTimeZoneProviderMode != null;
-    }
+    boolean isTestSecondaryLocationTimeZoneProvider();
 
     /**
      * Enables/disables the state recording mode for tests. The value is reset with {@link
      * #resetVolatileTestConfig()}.
      */
-    public void setRecordProviderStateChanges(boolean enabled) {
-        mRecordProviderStateChanges = enabled;
-    }
+    void setRecordStateChangesForTests(boolean enabled);
 
     /**
-     * Returns {@code true} if providers are expected to record their state changes for tests.
+     * Returns {@code true} if the controller / providers are expected to record their state changes
+     * for tests.
      */
-    public boolean getRecordProviderStateChanges() {
-        return mRecordProviderStateChanges;
-    }
+    boolean getRecordStateChangesForTests();
 
     /**
      * Returns the mode for the primary location time zone provider.
      */
     @NonNull
-    public @ProviderMode String getPrimaryLocationTimeZoneProviderMode() {
-        if (mTestPrimaryLocationTimeZoneProviderMode != null) {
-            // In test mode: use the test setting value.
-            return mTestPrimaryLocationTimeZoneProviderMode;
-        }
-        return mServerFlags.getOptionalString(ServerFlags.KEY_PRIMARY_LTZP_MODE_OVERRIDE)
-                .orElse(getPrimaryLocationTimeZoneProviderModeFromConfig());
-    }
-
-    @NonNull
-    private @ProviderMode String getPrimaryLocationTimeZoneProviderModeFromConfig() {
-        int providerEnabledConfigId = R.bool.config_enablePrimaryLocationTimeZoneProvider;
-        return getConfigBoolean(providerEnabledConfigId)
-                ? PROVIDER_MODE_ENABLED : PROVIDER_MODE_DISABLED;
-    }
+    @ProviderMode String getPrimaryLocationTimeZoneProviderMode();
 
     /**
      * Returns the mode for the secondary location time zone provider.
      */
-    public @ProviderMode String getSecondaryLocationTimeZoneProviderMode() {
-        if (mTestSecondaryLocationTimeZoneProviderMode != null) {
-            // In test mode: use the test setting value.
-            return mTestSecondaryLocationTimeZoneProviderMode;
-        }
-        return mServerFlags.getOptionalString(ServerFlags.KEY_SECONDARY_LTZP_MODE_OVERRIDE)
-                .orElse(getSecondaryLocationTimeZoneProviderModeFromConfig());
-    }
-
-    @NonNull
-    private @ProviderMode String getSecondaryLocationTimeZoneProviderModeFromConfig() {
-        int providerEnabledConfigId = R.bool.config_enableSecondaryLocationTimeZoneProvider;
-        return getConfigBoolean(providerEnabledConfigId)
-                ? PROVIDER_MODE_ENABLED : PROVIDER_MODE_DISABLED;
-    }
+    @ProviderMode String getSecondaryLocationTimeZoneProviderMode();
 
     /**
      * Returns whether location time zone detection is enabled for users when there's no setting
      * value. Intended for use during feature release testing to "opt-in" users that haven't shown
      * an explicit preference.
      */
-    public boolean isGeoDetectionEnabledForUsersByDefault() {
-        return mServerFlags.getBoolean(
-                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT, false);
-    }
+    boolean isGeoDetectionEnabledForUsersByDefault();
 
     /**
      * Returns whether location time zone detection is force enabled/disabled for users. Intended
      * for use during feature release testing to force a given state.
      */
     @NonNull
-    public Optional<Boolean> getGeoDetectionSettingEnabledOverride() {
-        return mServerFlags.getOptionalBoolean(
-                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE);
-    }
+    Optional<Boolean> getGeoDetectionSettingEnabledOverride();
 
     /**
      * Returns the time to send to a location time zone provider that informs it how long it has
      * to return its first time zone suggestion.
      */
     @NonNull
-    public Duration getLocationTimeZoneProviderInitializationTimeout() {
-        return mServerFlags.getDurationFromMillis(
-                ServerFlags.KEY_LTZP_INITIALIZATION_TIMEOUT_MILLIS,
-                DEFAULT_LTZP_INITIALIZATION_TIMEOUT);
-    }
+    Duration getLocationTimeZoneProviderInitializationTimeout();
 
     /**
      * Returns the time added to {@link #getLocationTimeZoneProviderInitializationTimeout()} by the
      * server before unilaterally declaring the provider is uncertain.
      */
     @NonNull
-    public Duration getLocationTimeZoneProviderInitializationTimeoutFuzz() {
-        return mServerFlags.getDurationFromMillis(
-                ServerFlags.KEY_LTZP_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
-                DEFAULT_LTZP_INITIALIZATION_TIMEOUT_FUZZ);
-    }
+    Duration getLocationTimeZoneProviderInitializationTimeoutFuzz();
 
     /**
      * Returns the time after uncertainty is detected by providers before the location time zone
      * manager makes a suggestion to the time zone detector.
      */
     @NonNull
-    public Duration getLocationTimeZoneUncertaintyDelay() {
-        return mServerFlags.getDurationFromMillis(
-                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS,
-                DEFAULT_LTZP_UNCERTAINTY_DELAY);
-    }
+    Duration getLocationTimeZoneUncertaintyDelay();
 
     /**
      * Returns the time between equivalent events before the provider process will send the event
      * to the system server.
      */
     @NonNull
-    public Duration getLocationTimeZoneProviderEventFilteringAgeThreshold() {
-        return mServerFlags.getDurationFromMillis(
-                ServerFlags.KEY_LTZP_EVENT_FILTERING_AGE_THRESHOLD_MILLIS,
-                DEFAULT_LTZP_EVENT_FILTER_AGE_THRESHOLD);
-    }
+    Duration getLocationTimeZoneProviderEventFilteringAgeThreshold();
 
     /** Clears all in-memory test config. */
-    public void resetVolatileTestConfig() {
-        mTestPrimaryLocationTimeZoneProviderPackageName = null;
-        mTestPrimaryLocationTimeZoneProviderMode = null;
-        mTestSecondaryLocationTimeZoneProviderPackageName = null;
-        mTestSecondaryLocationTimeZoneProviderMode = null;
-        mRecordProviderStateChanges = false;
-    }
-
-    private boolean getConfigBoolean(int providerEnabledConfigId) {
-        Resources resources = mContext.getResources();
-        return resources.getBoolean(providerEnabledConfigId);
-    }
+    void resetVolatileTestConfig();
 }
diff --git a/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
new file mode 100644
index 0000000..02ea433
--- /dev/null
+++ b/services/core/java/com/android/server/timezonedetector/ServiceConfigAccessorImpl.java
@@ -0,0 +1,565 @@
+/*
+ * Copyright 2021 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.timezonedetector;
+
+import static android.content.Intent.ACTION_USER_SWITCHED;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.app.ActivityManagerInternal;
+import android.app.time.TimeZoneCapabilities;
+import android.app.time.TimeZoneCapabilitiesAndConfig;
+import android.app.time.TimeZoneConfiguration;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.database.ContentObserver;
+import android.location.LocationManager;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.util.ArraySet;
+
+import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.LocalServices;
+import com.android.server.timedetector.ServerFlags;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * A singleton implementation of {@link ServiceConfigAccessor}.
+ */
+public final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
+
+    /**
+     * Device config keys that can affect the content of {@link ConfigurationInternal}.
+     */
+    private static final Set<String> CONFIGURATION_INTERNAL_SERVER_FLAGS_KEYS_TO_WATCH =
+            Collections.unmodifiableSet(new ArraySet<>(new String[] {
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
+                    ServerFlags.KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED,
+            }));
+
+    /**
+     * Device config keys that can affect {@link
+     * com.android.server.timezonedetector.location.LocationTimeZoneManagerService} behavior.
+     */
+    private static final Set<String> LOCATION_TIME_ZONE_MANAGER_SERVER_FLAGS_KEYS_TO_WATCH =
+            Collections.unmodifiableSet(new ArraySet<>(new String[] {
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT,
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE,
+                    ServerFlags.KEY_PRIMARY_LTZP_MODE_OVERRIDE,
+                    ServerFlags.KEY_SECONDARY_LTZP_MODE_OVERRIDE,
+                    ServerFlags.KEY_LTZP_INITIALIZATION_TIMEOUT_MILLIS,
+                    ServerFlags.KEY_LTZP_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
+                    ServerFlags.KEY_LTZP_EVENT_FILTERING_AGE_THRESHOLD_MILLIS,
+                    ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS
+            }));
+
+    private static final Duration DEFAULT_LTZP_INITIALIZATION_TIMEOUT = Duration.ofMinutes(5);
+    private static final Duration DEFAULT_LTZP_INITIALIZATION_TIMEOUT_FUZZ = Duration.ofMinutes(1);
+    private static final Duration DEFAULT_LTZP_UNCERTAINTY_DELAY = Duration.ofMinutes(5);
+    private static final Duration DEFAULT_LTZP_EVENT_FILTER_AGE_THRESHOLD = Duration.ofMinutes(1);
+
+    private static final Object SLOCK = new Object();
+
+    /** The singleton instance. Initialized once in {@link #getInstance(Context)}. */
+    @GuardedBy("SLOCK")
+    @Nullable
+    private static ServiceConfigAccessor sInstance;
+
+    @NonNull private final Context mContext;
+    @NonNull private final ServerFlags mServerFlags;
+    @NonNull private final ContentResolver mCr;
+    @NonNull private final UserManager mUserManager;
+    @NonNull private final LocationManager mLocationManager;
+
+    @GuardedBy("this")
+    @NonNull private final List<ConfigurationChangeListener> mConfigurationInternalListeners =
+            new ArrayList<>();
+
+    /**
+     * The mode to use for the primary location time zone provider in a test. Setting this
+     * disables some permission checks.
+     * This state is volatile: it is never written to storage / never survives a reboot. This is to
+     * avoid a test provider accidentally being left configured on a device.
+     * See also {@link #resetVolatileTestConfig()}.
+     */
+    @GuardedBy("this")
+    @Nullable
+    private String mTestPrimaryLocationTimeZoneProviderMode;
+
+    /**
+     * The package name to use for the primary location time zone provider in a test.
+     * This state is volatile: it is never written to storage / never survives a reboot. This is to
+     * avoid a test provider accidentally being left configured on a device.
+     * See also {@link #resetVolatileTestConfig()}.
+     */
+    @GuardedBy("this")
+    @Nullable
+    private String mTestPrimaryLocationTimeZoneProviderPackageName;
+
+    /**
+     * See {@link #mTestPrimaryLocationTimeZoneProviderMode}; this is the equivalent for the
+     * secondary provider.
+     */
+    @GuardedBy("this")
+    @Nullable
+    private String mTestSecondaryLocationTimeZoneProviderMode;
+
+    /**
+     * See {@link #mTestPrimaryLocationTimeZoneProviderPackageName}; this is the equivalent for the
+     * secondary provider.
+     */
+    @GuardedBy("this")
+    @Nullable
+    private String mTestSecondaryLocationTimeZoneProviderPackageName;
+
+    /**
+     * Whether to record state changes for tests.
+     * This state is volatile: it is never written to storage / never survives a reboot. This is to
+     * avoid a test state accidentally being left configured on a device.
+     * See also {@link #resetVolatileTestConfig()}.
+     */
+    @GuardedBy("this")
+    private boolean mRecordStateChangesForTests;
+
+    private ServiceConfigAccessorImpl(@NonNull Context context) {
+        mContext = Objects.requireNonNull(context);
+        mCr = context.getContentResolver();
+        mUserManager = context.getSystemService(UserManager.class);
+        mLocationManager = context.getSystemService(LocationManager.class);
+        mServerFlags = ServerFlags.getInstance(mContext);
+
+        // Wire up the config change listeners for anything that could affect ConfigurationInternal.
+        // Use the main thread for event delivery, listeners can post to their chosen thread.
+
+        // Listen for the user changing / the user's location mode changing. Report on the main
+        // thread.
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_USER_SWITCHED);
+        filter.addAction(LocationManager.MODE_CHANGED_ACTION);
+        mContext.registerReceiverForAllUsers(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                handleConfigurationInternalChangeOnMainThread();
+            }
+        }, filter, null, null /* main thread */);
+
+        // Add async callbacks for global settings being changed.
+        ContentResolver contentResolver = mContext.getContentResolver();
+        ContentObserver contentObserver = new ContentObserver(mContext.getMainThreadHandler()) {
+            @Override
+            public void onChange(boolean selfChange) {
+                handleConfigurationInternalChangeOnMainThread();
+            }
+        };
+        contentResolver.registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.AUTO_TIME_ZONE), true, contentObserver);
+
+        // Add async callbacks for user scoped location settings being changed.
+        contentResolver.registerContentObserver(
+                Settings.Secure.getUriFor(Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED),
+                true, contentObserver, UserHandle.USER_ALL);
+
+        // Watch server flags.
+        mServerFlags.addListener(this::handleConfigurationInternalChangeOnMainThread,
+                CONFIGURATION_INTERNAL_SERVER_FLAGS_KEYS_TO_WATCH);
+    }
+
+    /** Returns the singleton instance. */
+    public static ServiceConfigAccessor getInstance(Context context) {
+        synchronized (SLOCK) {
+            if (sInstance == null) {
+                sInstance = new ServiceConfigAccessorImpl(context);
+            }
+            return sInstance;
+        }
+    }
+
+    private synchronized void handleConfigurationInternalChangeOnMainThread() {
+        for (ConfigurationChangeListener changeListener : mConfigurationInternalListeners) {
+            changeListener.onChange();
+        }
+    }
+
+    @Override
+    public synchronized void addConfigurationInternalChangeListener(
+            @NonNull ConfigurationChangeListener listener) {
+        mConfigurationInternalListeners.add(Objects.requireNonNull(listener));
+    }
+
+    @Override
+    public synchronized void removeConfigurationInternalChangeListener(
+            @NonNull ConfigurationChangeListener listener) {
+        mConfigurationInternalListeners.remove(Objects.requireNonNull(listener));
+    }
+
+    @Override
+    @NonNull
+    public synchronized ConfigurationInternal getCurrentUserConfigurationInternal() {
+        int currentUserId =
+                LocalServices.getService(ActivityManagerInternal.class).getCurrentUserId();
+        return getConfigurationInternal(currentUserId);
+    }
+
+    @Override
+    public synchronized boolean updateConfiguration(@UserIdInt int userId,
+            @NonNull TimeZoneConfiguration requestedConfiguration) {
+        Objects.requireNonNull(requestedConfiguration);
+
+        TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+                getConfigurationInternal(userId).createCapabilitiesAndConfig();
+        TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+        TimeZoneConfiguration oldConfiguration = capabilitiesAndConfig.getConfiguration();
+
+        final TimeZoneConfiguration newConfiguration =
+                capabilities.tryApplyConfigChanges(oldConfiguration, requestedConfiguration);
+        if (newConfiguration == null) {
+            // The changes could not be made because the user's capabilities do not allow it.
+            return false;
+        }
+
+        // Store the configuration / notify as needed. This will cause the mEnvironment to invoke
+        // handleConfigChanged() asynchronously.
+        storeConfiguration(userId, newConfiguration);
+
+        return true;
+    }
+
+    /**
+     * Stores the configuration properties contained in {@code newConfiguration}.
+     * All checks about user capabilities must be done by the caller and
+     * {@link TimeZoneConfiguration#isComplete()} must be {@code true}.
+     */
+    @GuardedBy("this")
+    private void storeConfiguration(@UserIdInt int userId,
+            @NonNull TimeZoneConfiguration configuration) {
+        Objects.requireNonNull(configuration);
+
+        // Avoid writing the auto detection enabled setting for devices that do not support auto
+        // time zone detection: if we wrote it down then we'd set the value explicitly, which would
+        // prevent detecting "default" later. That might influence what happens on later releases
+        // that support new types of auto detection on the same hardware.
+        if (isAutoDetectionFeatureSupported()) {
+            final boolean autoDetectionEnabled = configuration.isAutoDetectionEnabled();
+            setAutoDetectionEnabledIfRequired(autoDetectionEnabled);
+
+            // Avoid writing the geo detection enabled setting for devices with settings that
+            // are currently overridden by server flags: otherwise we might overwrite a droidfood
+            // user's real setting permanently.
+            // Also avoid writing the geo detection enabled setting for devices that do not support
+            // geo time zone detection: if we wrote it down then we'd set the value explicitly,
+            // which would prevent detecting "default" later. That might influence what happens on
+            // later releases that start to support geo detection on the same hardware.
+            if (!getGeoDetectionSettingEnabledOverride().isPresent()
+                    && isGeoTimeZoneDetectionFeatureSupported()) {
+                final boolean geoDetectionEnabledSetting = configuration.isGeoDetectionEnabled();
+                setGeoDetectionEnabledSettingIfRequired(userId, geoDetectionEnabledSetting);
+            }
+        }
+    }
+
+    @Override
+    @NonNull
+    public synchronized ConfigurationInternal getConfigurationInternal(@UserIdInt int userId) {
+        return new ConfigurationInternal.Builder(userId)
+                .setTelephonyDetectionFeatureSupported(
+                        isTelephonyTimeZoneDetectionFeatureSupported())
+                .setGeoDetectionFeatureSupported(isGeoTimeZoneDetectionFeatureSupported())
+                .setTelephonyFallbackSupported(isTelephonyFallbackSupported())
+                .setAutoDetectionEnabledSetting(getAutoDetectionEnabledSetting())
+                .setUserConfigAllowed(isUserConfigAllowed(userId))
+                .setLocationEnabledSetting(getLocationEnabledSetting(userId))
+                .setGeoDetectionEnabledSetting(getGeoDetectionEnabledSetting(userId))
+                .build();
+    }
+
+    private void setAutoDetectionEnabledIfRequired(boolean enabled) {
+        // This check is racey, but the whole settings update process is racey. This check prevents
+        // a ConfigurationChangeListener callback triggering due to ContentObserver's still
+        // triggering *sometimes* for no-op updates. Because callbacks are async this is necessary
+        // for stable behavior during tests.
+        if (getAutoDetectionEnabledSetting() != enabled) {
+            Settings.Global.putInt(mCr, Settings.Global.AUTO_TIME_ZONE, enabled ? 1 : 0);
+        }
+    }
+
+    private boolean getLocationEnabledSetting(@UserIdInt int userId) {
+        return mLocationManager.isLocationEnabledForUser(UserHandle.of(userId));
+    }
+
+    private boolean isUserConfigAllowed(@UserIdInt int userId) {
+        UserHandle userHandle = UserHandle.of(userId);
+        return !mUserManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_DATE_TIME, userHandle);
+    }
+
+    private boolean getAutoDetectionEnabledSetting() {
+        return Settings.Global.getInt(mCr, Settings.Global.AUTO_TIME_ZONE, 1 /* default */) > 0;
+    }
+
+    private boolean getGeoDetectionEnabledSetting(@UserIdInt int userId) {
+        // We may never use this, but it gives us a way to force location-based time zone detection
+        // on/off for testers (but only where their other settings would allow them to turn it on
+        // for themselves).
+        Optional<Boolean> override = getGeoDetectionSettingEnabledOverride();
+        if (override.isPresent()) {
+            return override.get();
+        }
+
+        final boolean geoDetectionEnabledByDefault = isGeoDetectionEnabledForUsersByDefault();
+        return Settings.Secure.getIntForUser(mCr,
+                Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED,
+                (geoDetectionEnabledByDefault ? 1 : 0) /* defaultValue */, userId) != 0;
+    }
+
+    private void setGeoDetectionEnabledSettingIfRequired(@UserIdInt int userId, boolean enabled) {
+        // See comment in setAutoDetectionEnabledIfRequired. http://b/171953500
+        if (getGeoDetectionEnabledSetting(userId) != enabled) {
+            Settings.Secure.putIntForUser(mCr, Settings.Secure.LOCATION_TIME_ZONE_DETECTION_ENABLED,
+                    enabled ? 1 : 0, userId);
+        }
+    }
+
+    @Override
+    public void addLocationTimeZoneManagerConfigListener(
+            @NonNull ConfigurationChangeListener listener) {
+        mServerFlags.addListener(listener, LOCATION_TIME_ZONE_MANAGER_SERVER_FLAGS_KEYS_TO_WATCH);
+    }
+
+    /** Returns {@code true} if any form of automatic time zone detection is supported. */
+    private boolean isAutoDetectionFeatureSupported() {
+        return isTelephonyTimeZoneDetectionFeatureSupported()
+                || isGeoTimeZoneDetectionFeatureSupported();
+    }
+
+    @Override
+    public boolean isTelephonyTimeZoneDetectionFeatureSupported() {
+        return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
+    }
+
+    @Override
+    public boolean isGeoTimeZoneDetectionFeatureSupportedInConfig() {
+        return mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_enableGeolocationTimeZoneDetection);
+    }
+
+    @Override
+    public boolean isGeoTimeZoneDetectionFeatureSupported() {
+        // For the feature to be enabled it must:
+        // 1) Be turned on in config.
+        // 2) Not be turned off via a server flag.
+        // 3) There must be at least one location time zone provider enabled / configured.
+        return isGeoTimeZoneDetectionFeatureSupportedInConfig()
+                && isGeoTimeZoneDetectionFeatureSupportedInternal()
+                && atLeastOneProviderIsEnabled();
+    }
+
+    private boolean atLeastOneProviderIsEnabled() {
+        return !(Objects.equals(getPrimaryLocationTimeZoneProviderMode(), PROVIDER_MODE_DISABLED)
+                && Objects.equals(getSecondaryLocationTimeZoneProviderMode(),
+                PROVIDER_MODE_DISABLED));
+    }
+
+    /**
+     * Returns {@code true} if the location-based time zone detection feature is not explicitly
+     * disabled by a server flag.
+     */
+    private boolean isGeoTimeZoneDetectionFeatureSupportedInternal() {
+        final boolean defaultEnabled = true;
+        return mServerFlags.getBoolean(
+                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED,
+                defaultEnabled);
+    }
+
+    @Override
+    @NonNull
+    public synchronized String getPrimaryLocationTimeZoneProviderPackageName() {
+        if (mTestPrimaryLocationTimeZoneProviderMode != null) {
+            // In test mode: use the test setting value.
+            return mTestPrimaryLocationTimeZoneProviderPackageName;
+        }
+        return mContext.getResources().getString(
+                R.string.config_primaryLocationTimeZoneProviderPackageName);
+    }
+
+    @Override
+    public synchronized void setTestPrimaryLocationTimeZoneProviderPackageName(
+            @Nullable String testPrimaryLocationTimeZoneProviderPackageName) {
+        mTestPrimaryLocationTimeZoneProviderPackageName =
+                testPrimaryLocationTimeZoneProviderPackageName;
+        mTestPrimaryLocationTimeZoneProviderMode =
+                mTestPrimaryLocationTimeZoneProviderPackageName == null
+                        ? PROVIDER_MODE_DISABLED : PROVIDER_MODE_ENABLED;
+    }
+
+    @Override
+    public synchronized boolean isTestPrimaryLocationTimeZoneProvider() {
+        return mTestPrimaryLocationTimeZoneProviderMode != null;
+    }
+
+    @Override
+    @NonNull
+    public synchronized String getSecondaryLocationTimeZoneProviderPackageName() {
+        if (mTestSecondaryLocationTimeZoneProviderMode != null) {
+            // In test mode: use the test setting value.
+            return mTestSecondaryLocationTimeZoneProviderPackageName;
+        }
+        return mContext.getResources().getString(
+                R.string.config_secondaryLocationTimeZoneProviderPackageName);
+    }
+
+    @Override
+    public synchronized void setTestSecondaryLocationTimeZoneProviderPackageName(
+            @Nullable String testSecondaryLocationTimeZoneProviderPackageName) {
+        mTestSecondaryLocationTimeZoneProviderPackageName =
+                testSecondaryLocationTimeZoneProviderPackageName;
+        mTestSecondaryLocationTimeZoneProviderMode =
+                mTestSecondaryLocationTimeZoneProviderPackageName == null
+                        ? PROVIDER_MODE_DISABLED : PROVIDER_MODE_ENABLED;
+    }
+
+    @Override
+    public synchronized boolean isTestSecondaryLocationTimeZoneProvider() {
+        return mTestSecondaryLocationTimeZoneProviderMode != null;
+    }
+
+    @Override
+    public synchronized void setRecordStateChangesForTests(boolean enabled) {
+        mRecordStateChangesForTests = enabled;
+    }
+
+    @Override
+    public synchronized boolean getRecordStateChangesForTests() {
+        return mRecordStateChangesForTests;
+    }
+
+    @Override
+    @NonNull
+    public synchronized @ProviderMode String getPrimaryLocationTimeZoneProviderMode() {
+        if (mTestPrimaryLocationTimeZoneProviderMode != null) {
+            // In test mode: use the test setting value.
+            return mTestPrimaryLocationTimeZoneProviderMode;
+        }
+        return mServerFlags.getOptionalString(ServerFlags.KEY_PRIMARY_LTZP_MODE_OVERRIDE)
+                .orElse(getPrimaryLocationTimeZoneProviderModeFromConfig());
+    }
+
+    @NonNull
+    private synchronized @ProviderMode String getPrimaryLocationTimeZoneProviderModeFromConfig() {
+        int providerEnabledConfigId = R.bool.config_enablePrimaryLocationTimeZoneProvider;
+        return getConfigBoolean(providerEnabledConfigId)
+                ? PROVIDER_MODE_ENABLED : PROVIDER_MODE_DISABLED;
+    }
+
+    @Override
+    public synchronized @ProviderMode String getSecondaryLocationTimeZoneProviderMode() {
+        if (mTestSecondaryLocationTimeZoneProviderMode != null) {
+            // In test mode: use the test setting value.
+            return mTestSecondaryLocationTimeZoneProviderMode;
+        }
+        return mServerFlags.getOptionalString(ServerFlags.KEY_SECONDARY_LTZP_MODE_OVERRIDE)
+                .orElse(getSecondaryLocationTimeZoneProviderModeFromConfig());
+    }
+
+    @NonNull
+    private synchronized @ProviderMode String getSecondaryLocationTimeZoneProviderModeFromConfig() {
+        int providerEnabledConfigId = R.bool.config_enableSecondaryLocationTimeZoneProvider;
+        return getConfigBoolean(providerEnabledConfigId)
+                ? PROVIDER_MODE_ENABLED : PROVIDER_MODE_DISABLED;
+    }
+
+    @Override
+    public boolean isGeoDetectionEnabledForUsersByDefault() {
+        return mServerFlags.getBoolean(
+                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT, false);
+    }
+
+    @Override
+    @NonNull
+    public Optional<Boolean> getGeoDetectionSettingEnabledOverride() {
+        return mServerFlags.getOptionalBoolean(
+                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE);
+    }
+
+    @Override
+    @NonNull
+    public Duration getLocationTimeZoneProviderInitializationTimeout() {
+        return mServerFlags.getDurationFromMillis(
+                ServerFlags.KEY_LTZP_INITIALIZATION_TIMEOUT_MILLIS,
+                DEFAULT_LTZP_INITIALIZATION_TIMEOUT);
+    }
+
+    @Override
+    @NonNull
+    public Duration getLocationTimeZoneProviderInitializationTimeoutFuzz() {
+        return mServerFlags.getDurationFromMillis(
+                ServerFlags.KEY_LTZP_INITIALIZATION_TIMEOUT_FUZZ_MILLIS,
+                DEFAULT_LTZP_INITIALIZATION_TIMEOUT_FUZZ);
+    }
+
+    @Override
+    @NonNull
+    public Duration getLocationTimeZoneUncertaintyDelay() {
+        return mServerFlags.getDurationFromMillis(
+                ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_UNCERTAINTY_DELAY_MILLIS,
+                DEFAULT_LTZP_UNCERTAINTY_DELAY);
+    }
+
+    @Override
+    @NonNull
+    public Duration getLocationTimeZoneProviderEventFilteringAgeThreshold() {
+        return mServerFlags.getDurationFromMillis(
+                ServerFlags.KEY_LTZP_EVENT_FILTERING_AGE_THRESHOLD_MILLIS,
+                DEFAULT_LTZP_EVENT_FILTER_AGE_THRESHOLD);
+    }
+
+    @Override
+    public synchronized void resetVolatileTestConfig() {
+        mTestPrimaryLocationTimeZoneProviderPackageName = null;
+        mTestPrimaryLocationTimeZoneProviderMode = null;
+        mTestSecondaryLocationTimeZoneProviderPackageName = null;
+        mTestSecondaryLocationTimeZoneProviderMode = null;
+        mRecordStateChangesForTests = false;
+    }
+
+    private boolean isTelephonyFallbackSupported() {
+        return mServerFlags.getBoolean(
+                ServerFlags.KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED,
+                getConfigBoolean(
+                        com.android.internal.R.bool.config_supportTelephonyTimeZoneFallback));
+    }
+
+    private boolean getConfigBoolean(int providerEnabledConfigId) {
+        Resources resources = mContext.getResources();
+        return resources.getBoolean(providerEnabledConfigId);
+    }
+}
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
index d429b87..b6ce802 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternal.java
@@ -25,24 +25,7 @@
  * <p>The methods on this class can be called from any thread.
  * @hide
  */
-public interface TimeZoneDetectorInternal extends Dumpable.Container {
-
-    /** Adds a listener that will be invoked when {@link ConfigurationInternal} may have changed. */
-    void addConfigurationListener(@NonNull ConfigurationChangeListener listener);
-
-    /**
-     * Removes a listener previously added via {@link
-     * #addConfigurationListener(ConfigurationChangeListener)}.
-     */
-    void removeConfigurationListener(@NonNull ConfigurationChangeListener listener);
-
-    /**
-     * Returns a snapshot of the {@link ConfigurationInternal} for the current user. This is only a
-     * snapshot so callers must use {@link #addConfigurationListener(ConfigurationChangeListener)}
-     * to be notified when it changes.
-     */
-    @NonNull
-    ConfigurationInternal getCurrentUserConfigurationInternal();
+public interface TimeZoneDetectorInternal {
 
     /**
      * Suggests the current time zone, determined using geolocation, to the detector. The
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java
index 4e78f5a..f61df82 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorInternalImpl.java
@@ -20,8 +20,6 @@
 import android.content.Context;
 import android.os.Handler;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.Objects;
 
 /**
@@ -34,51 +32,12 @@
     @NonNull private final Context mContext;
     @NonNull private final Handler mHandler;
     @NonNull private final TimeZoneDetectorStrategy mTimeZoneDetectorStrategy;
-    @NonNull private final List<ConfigurationChangeListener> mConfigurationListeners =
-            new ArrayList<>();
 
     public TimeZoneDetectorInternalImpl(@NonNull Context context, @NonNull Handler handler,
             @NonNull TimeZoneDetectorStrategy timeZoneDetectorStrategy) {
         mContext = Objects.requireNonNull(context);
         mHandler = Objects.requireNonNull(handler);
         mTimeZoneDetectorStrategy = Objects.requireNonNull(timeZoneDetectorStrategy);
-
-        // Wire up a change listener so that any downstream listeners can be notified when
-        // the configuration changes for any reason.
-        mTimeZoneDetectorStrategy.addConfigChangeListener(this::handleConfigurationChanged);
-    }
-
-    private void handleConfigurationChanged() {
-        synchronized (mConfigurationListeners) {
-            for (ConfigurationChangeListener listener : mConfigurationListeners) {
-                listener.onChange();
-            }
-        }
-    }
-
-    @Override
-    public void addDumpable(@NonNull Dumpable dumpable) {
-        mTimeZoneDetectorStrategy.addDumpable(dumpable);
-    }
-
-    @Override
-    public void addConfigurationListener(ConfigurationChangeListener listener) {
-        synchronized (mConfigurationListeners) {
-            mConfigurationListeners.add(Objects.requireNonNull(listener));
-        }
-    }
-
-    @Override
-    public void removeConfigurationListener(ConfigurationChangeListener listener) {
-        synchronized (mConfigurationListeners) {
-            mConfigurationListeners.remove(Objects.requireNonNull(listener));
-        }
-    }
-
-    @Override
-    @NonNull
-    public ConfigurationInternal getCurrentUserConfigurationInternal() {
-        return mTimeZoneDetectorStrategy.getCurrentUserConfigurationInternal();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
index b1b537b..14784cf 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorService.java
@@ -45,6 +45,8 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -59,6 +61,7 @@
         implements IBinder.DeathRecipient {
 
     static final String TAG = "time_zone_detector";
+    static final boolean DBG = false;
 
     /**
      * Handles the service lifecycle for {@link TimeZoneDetectorService} and
@@ -77,9 +80,19 @@
             Handler handler = FgThread.getHandler();
 
             ServiceConfigAccessor serviceConfigAccessor =
-                    ServiceConfigAccessor.getInstance(context);
+                    ServiceConfigAccessorImpl.getInstance(context);
             TimeZoneDetectorStrategy timeZoneDetectorStrategy =
                     TimeZoneDetectorStrategyImpl.create(context, handler, serviceConfigAccessor);
+            DeviceActivityMonitor deviceActivityMonitor =
+                    DeviceActivityMonitorImpl.create(context, handler);
+
+            // Wire up the telephony fallback behavior to activity detection.
+            deviceActivityMonitor.addListener(new DeviceActivityMonitor.Listener() {
+                @Override
+                public void onFlightComplete() {
+                    timeZoneDetectorStrategy.enableTelephonyTimeZoneFallback();
+                }
+            });
 
             // Create and publish the local service for use by internal callers.
             TimeZoneDetectorInternal internal =
@@ -89,7 +102,11 @@
             // Publish the binder service so it can be accessed from other (appropriately
             // permissioned) processes.
             TimeZoneDetectorService service = TimeZoneDetectorService.create(
-                    context, handler, timeZoneDetectorStrategy);
+                    context, handler, serviceConfigAccessor, timeZoneDetectorStrategy);
+
+            // Dump the device activity monitor when the service is dumped.
+            service.addDumpable(deviceActivityMonitor);
+
             publishBinderService(Context.TIME_ZONE_DETECTOR_SERVICE, service);
         }
     }
@@ -104,6 +121,9 @@
     private final CallerIdentityInjector mCallerIdentityInjector;
 
     @NonNull
+    private final ServiceConfigAccessor mServiceConfigAccessor;
+
+    @NonNull
     private final TimeZoneDetectorStrategy mTimeZoneDetectorStrategy;
 
     /**
@@ -112,31 +132,40 @@
      */
     @GuardedBy("mListeners")
     @NonNull
-    private final ArrayMap<IBinder, ITimeZoneDetectorListener> mListeners =
-            new ArrayMap<>();
+    private final ArrayMap<IBinder, ITimeZoneDetectorListener> mListeners = new ArrayMap<>();
+
+    /**
+     * References to components that should be dumped when {@link
+     * #dump(FileDescriptor, PrintWriter, String[])} is called on the service.
+     */
+    @GuardedBy("mDumpables")
+    private final List<Dumpable> mDumpables = new ArrayList<>();
 
     private static TimeZoneDetectorService create(
             @NonNull Context context, @NonNull Handler handler,
+            @NonNull ServiceConfigAccessor serviceConfigAccessor,
             @NonNull TimeZoneDetectorStrategy timeZoneDetectorStrategy) {
 
         CallerIdentityInjector callerIdentityInjector = CallerIdentityInjector.REAL;
-        TimeZoneDetectorService service = new TimeZoneDetectorService(
-                context, handler, callerIdentityInjector, timeZoneDetectorStrategy);
-        return service;
+        return new TimeZoneDetectorService(context, handler, callerIdentityInjector,
+                serviceConfigAccessor, timeZoneDetectorStrategy);
     }
 
     @VisibleForTesting
     public TimeZoneDetectorService(@NonNull Context context, @NonNull Handler handler,
             @NonNull CallerIdentityInjector callerIdentityInjector,
+            @NonNull ServiceConfigAccessor serviceConfigAccessor,
             @NonNull TimeZoneDetectorStrategy timeZoneDetectorStrategy) {
         mContext = Objects.requireNonNull(context);
         mHandler = Objects.requireNonNull(handler);
         mCallerIdentityInjector = Objects.requireNonNull(callerIdentityInjector);
+        mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
         mTimeZoneDetectorStrategy = Objects.requireNonNull(timeZoneDetectorStrategy);
 
         // Wire up a change listener so that ITimeZoneDetectorListeners can be notified when
         // the configuration changes for any reason.
-        mTimeZoneDetectorStrategy.addConfigChangeListener(this::handleConfigurationChanged);
+        mServiceConfigAccessor.addConfigurationInternalChangeListener(
+                () -> mHandler.post(this::handleConfigurationInternalChangedOnHandlerThread));
     }
 
     @Override
@@ -152,7 +181,7 @@
         final long token = mCallerIdentityInjector.clearCallingIdentity();
         try {
             ConfigurationInternal configurationInternal =
-                    mTimeZoneDetectorStrategy.getConfigurationInternal(userId);
+                    mServiceConfigAccessor.getConfigurationInternal(userId);
             return configurationInternal.createCapabilitiesAndConfig();
         } finally {
             mCallerIdentityInjector.restoreCallingIdentity(token);
@@ -176,7 +205,7 @@
 
         final long token = mCallerIdentityInjector.clearCallingIdentity();
         try {
-            return mTimeZoneDetectorStrategy.updateConfiguration(userId, configuration);
+            return mServiceConfigAccessor.updateConfiguration(userId, configuration);
         } finally {
             mCallerIdentityInjector.restoreCallingIdentity(token);
         }
@@ -251,12 +280,12 @@
             if (!removedListener) {
                 Slog.w(TAG, "Notified of binder death for who=" + who
                         + ", but did not remove any listeners."
-                        + " mConfigurationListeners=" + mListeners);
+                        + " mListeners=" + mListeners);
             }
         }
     }
 
-    void handleConfigurationChanged() {
+    void handleConfigurationInternalChangedOnHandlerThread() {
         // Configuration has changed, but each user may have a different view of the configuration.
         // It's possible that this will cause unnecessary notifications but that shouldn't be a
         // problem.
@@ -307,15 +336,32 @@
     boolean isTelephonyTimeZoneDetectionSupported() {
         enforceManageTimeZoneDetectorPermission();
 
-        return ServiceConfigAccessor.getInstance(mContext)
-                .isTelephonyTimeZoneDetectionFeatureSupported();
+        return mServiceConfigAccessor.isTelephonyTimeZoneDetectionFeatureSupported();
     }
 
     boolean isGeoTimeZoneDetectionSupported() {
         enforceManageTimeZoneDetectorPermission();
 
-        return ServiceConfigAccessor.getInstance(mContext)
-                .isGeoTimeZoneDetectionFeatureSupported();
+        return mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupported();
+    }
+
+    /**
+     * Sends a signal to enable telephony fallback. Provided for command-line access for use
+     * during tests. This is not exposed as a binder API.
+     */
+    void enableTelephonyFallback() {
+        enforceManageTimeZoneDetectorPermission();
+        mTimeZoneDetectorStrategy.enableTelephonyTimeZoneFallback();
+    }
+
+    /**
+     * Registers the supplied {@link Dumpable} for dumping. When the service is dumped
+     * {@link Dumpable#dump(IndentingPrintWriter, String[])} will be called on the {@code dumpable}.
+     */
+    void addDumpable(@NonNull Dumpable dumpable) {
+        synchronized (mDumpables) {
+            mDumpables.add(dumpable);
+        }
     }
 
     @Override
@@ -325,6 +371,13 @@
 
         IndentingPrintWriter ipw = new IndentingPrintWriter(pw);
         mTimeZoneDetectorStrategy.dump(ipw, args);
+
+        synchronized (mDumpables) {
+            for (Dumpable dumpable : mDumpables) {
+                dumpable.dump(ipw, args);
+            }
+        }
+
         ipw.flush();
     }
 
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
index a4a46a3..2b912ad 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorShellCommand.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.timezonedetector;
 
+import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_ENABLE_TELEPHONY_FALLBACK;
 import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_AUTO_DETECTION_ENABLED;
 import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_GEO_DETECTION_ENABLED;
 import static android.app.timezonedetector.TimeZoneDetector.SHELL_COMMAND_IS_GEO_DETECTION_SUPPORTED;
@@ -30,6 +31,7 @@
 import static com.android.server.timedetector.ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_FEATURE_SUPPORTED;
 import static com.android.server.timedetector.ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_DEFAULT;
 import static com.android.server.timedetector.ServerFlags.KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE;
+import static com.android.server.timedetector.ServerFlags.KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED;
 
 import android.app.time.LocationTimeZoneManager;
 import android.app.time.TimeZoneConfiguration;
@@ -76,6 +78,8 @@
                 return runSuggestManualTimeZone();
             case SHELL_COMMAND_SUGGEST_TELEPHONY_TIME_ZONE:
                 return runSuggestTelephonyTimeZone();
+            case SHELL_COMMAND_ENABLE_TELEPHONY_FALLBACK:
+                return runEnableTelephonyFallback();
             default: {
                 return handleDefaultCommands(cmd);
             }
@@ -169,6 +173,11 @@
         }
     }
 
+    private int runEnableTelephonyFallback() {
+        mInterface.enableTelephonyFallback();
+        return 1;
+    }
+
     @Override
     public void onHelp() {
         final PrintWriter pw = getOutPrintWriter();
@@ -190,6 +199,13 @@
                 + "\n");
         pw.printf("  %s true|false\n", SHELL_COMMAND_SET_GEO_DETECTION_ENABLED);
         pw.printf("    Sets the geolocation time zone detection enabled setting.\n");
+        pw.printf("  %s\n", SHELL_COMMAND_ENABLE_TELEPHONY_FALLBACK);
+        pw.printf("    Signals that telephony time zone detection fall back can be used if"
+                + " geolocation detection is supported and enabled. This is a temporary state until"
+                + " geolocation detection becomes \"certain\". To have an effect this requires that"
+                + " the telephony fallback feature is supported on the device, see below for"
+                + " for device_config flags.\n");
+        pw.println();
         pw.printf("  %s <geolocation suggestion opts>\n",
                 SHELL_COMMAND_SUGGEST_GEO_LOCATION_TIME_ZONE);
         pw.printf("  %s <manual suggestion opts>\n",
@@ -216,6 +232,9 @@
         pw.printf("  %s\n", KEY_LOCATION_TIME_ZONE_DETECTION_SETTING_ENABLED_OVERRIDE);
         pw.printf("    Used to override the device's 'geolocation time zone detection enabled'"
                 + " setting [*].\n");
+        pw.printf("  %s\n", KEY_TIME_ZONE_DETECTOR_TELEPHONY_FALLBACK_SUPPORTED);
+        pw.printf("    Used to enable / disable support for telephony detection fallback. Also see"
+                + " the %s command.\n", SHELL_COMMAND_ENABLE_TELEPHONY_FALLBACK);
         pw.println();
         pw.printf("[*] To be enabled, the user must still have location = on / auto time zone"
                 + " detection = on.\n");
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
index e3f31b6..6b04adf 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategy.java
@@ -17,7 +17,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
-import android.app.time.TimeZoneConfiguration;
 import android.app.timezonedetector.ManualTimeZoneSuggestion;
 import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
 import android.util.IndentingPrintWriter;
@@ -30,7 +29,7 @@
  * Suggestions are acted on or ignored as needed, depending on previously received suggestions and
  * the current user's configuration (see {@link ConfigurationInternal}).
  *
- * <p>Devices can have zero, one or two automatic time zone detection algorithm available at any
+ * <p>Devices can have zero, one or two automatic time zone detection algorithms available at any
  * point in time.
  *
  * <p>The two automatic detection algorithms supported are "telephony" and "geolocation". Algorithm
@@ -63,46 +62,36 @@
  * have an empty suggestion submitted in order to "withdraw" their previous suggestion otherwise it
  * will remain in use.
  *
+ * <p>The strategy uses only one algorithm at a time and does not attempt consensus even when
+ * more than one is available on a device. This "use only one" behavior is deliberate as different
+ * algorithms have edge cases and blind spots that lead to incorrect answers or uncertainty;
+ * different algorithms aren't guaranteed to agree, and algorithms may frequently lose certainty as
+ * users enter areas without the necessary signals. Ultimately, with no perfect algorithm available,
+ * the user is left to choose which algorithm works best for their circumstances.
+ *
+ * <p>When geolocation detection is supported and enabled, in certain circumstances, such as during
+ * international travel, it makes sense to prioritize speed of detection via telephony (when
+ * available) Vs waiting for the geolocation algorithm to reach certainty. Geolocation detection can
+ * sometimes be slow to get a location fix and can require network connectivity (which cannot be
+ * assumed when users are travelling) for server-assisted location detection or time zone lookup.
+ * Therefore, as a restricted form of prioritization between geolocation and telephony algorithms,
+ * the strategy provides "telephony fallback" behavior, which can be set to "supported" via device
+ * config. Fallback mode is toggled on at runtime via {@link #enableTelephonyTimeZoneFallback()} in
+ * response to signals outside of the scope of this class. Telephony fallback allows the use of
+ * telephony suggestions to help with faster detection but only until geolocation detection
+ * provides a concrete, "certain" suggestion. After geolocation has made the first certain
+ * suggestion, telephony fallback is disabled until the next call to {@link
+ * #enableTelephonyTimeZoneFallback()}.
+ *
  * <p>Threading:
  *
- * <p>Suggestion calls with a void return type may be handed off to a separate thread and handled
- * asynchronously. Synchronous calls like {@link #getCurrentUserConfigurationInternal()},
- * {@link #generateMetricsState()} and debug calls like {@link
- * #dump(IndentingPrintWriter, String[])}, may be called on a different thread concurrently with
- * other operations.
+ * <p>Implementations of this class must be thread-safe as calls calls like {@link
+ * #generateMetricsState()} and {@link #dump(IndentingPrintWriter, String[])} may be called on
+ * differents thread concurrently with other operations.
  *
  * @hide
  */
-public interface TimeZoneDetectorStrategy extends Dumpable, Dumpable.Container {
-
-    /**
-     * Adds a listener that will be triggered whenever {@link ConfigurationInternal} may have
-     * changed.
-     */
-    void addConfigChangeListener(@NonNull ConfigurationChangeListener listener);
-
-    /**
-     * Returns a snapshot of the configuration that controls time zone detector behavior for the
-     * specified user.
-     */
-    @NonNull
-    ConfigurationInternal getConfigurationInternal(@UserIdInt int userId);
-
-    /**
-     * Returns a snapshot of the configuration that controls time zone detector behavior for the
-     * current user.
-     */
-    @NonNull
-    ConfigurationInternal getCurrentUserConfigurationInternal();
-
-    /**
-     * Updates the configuration properties that control a device's time zone behavior.
-     *
-     * <p>This method returns {@code true} if the configuration was changed,
-     * {@code false} otherwise.
-     */
-    boolean updateConfiguration(
-            @UserIdInt int userId, @NonNull TimeZoneConfiguration configuration);
+public interface TimeZoneDetectorStrategy extends Dumpable {
 
     /**
      * Suggests zero, one or more time zones for the device, or withdraws a previous suggestion if
@@ -125,6 +114,13 @@
      */
     void suggestTelephonyTimeZone(@NonNull TelephonyTimeZoneSuggestion suggestion);
 
+    /**
+     * Tells the strategy that it can fall back to telephony detection while geolocation detection
+     * remains uncertain. {@link #suggestGeolocationTimeZone(GeolocationTimeZoneSuggestion)} can
+     * disable it again. See {@link TimeZoneDetectorStrategy} for details.
+     */
+    void enableTelephonyTimeZoneFallback();
+
     /** Generates a state snapshot for metrics. */
     @NonNull
     MetricsTimeZoneDetectorState generateMetricsState();
diff --git a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
index ab2a88b..92dddac 100644
--- a/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/TimeZoneDetectorStrategyImpl.java
@@ -22,16 +22,17 @@
 import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_MULTIPLE_ZONES_WITH_SAME_OFFSET;
 import static android.app.timezonedetector.TelephonyTimeZoneSuggestion.QUALITY_SINGLE_ZONE;
 
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.app.time.TimeZoneCapabilities;
 import android.app.time.TimeZoneCapabilitiesAndConfig;
-import android.app.time.TimeZoneConfiguration;
 import android.app.timezonedetector.ManualTimeZoneSuggestion;
 import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
 import android.content.Context;
 import android.os.Handler;
+import android.os.TimestampedValue;
 import android.util.IndentingPrintWriter;
 import android.util.LocalLog;
 import android.util.Slog;
@@ -39,7 +40,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
-import java.util.ArrayList;
+import java.time.Duration;
 import java.util.List;
 import java.util.Objects;
 
@@ -63,16 +64,13 @@
 
         /**
          * Sets a {@link ConfigurationChangeListener} that will be invoked when there are any
-         * changes that could affect time zone detection. This is invoked during system server
-         * setup.
+         * changes that could affect the content of {@link ConfigurationInternal}.
+         * This is invoked during system server setup.
          */
-        void setConfigChangeListener(@NonNull ConfigurationChangeListener listener);
+        void setConfigurationInternalChangeListener(@NonNull ConfigurationChangeListener listener);
 
-        /** Returns the current user at the instant it is called. */
-        @UserIdInt int getCurrentUserId();
-
-        /** Returns the {@link ConfigurationInternal} for the specified user. */
-        ConfigurationInternal getConfigurationInternal(@UserIdInt int userId);
+        /** Returns the {@link ConfigurationInternal} for the current user. */
+        @NonNull ConfigurationInternal getCurrentUserConfigurationInternal();
 
         /**
          * Returns true if the device has had an explicit time zone set.
@@ -90,15 +88,15 @@
         void setDeviceTimeZone(@NonNull String zoneId);
 
         /**
-         * Stores the configuration properties contained in {@code newConfiguration}.
-         * All checks about user capabilities must be done by the caller and
-         * {@link TimeZoneConfiguration#isComplete()} must be {@code true}.
+         * Returns the time according to the elapsed realtime clock, the same as {@link
+         * android.os.SystemClock#elapsedRealtime()}.
          */
-        void storeConfiguration(@UserIdInt int userId, TimeZoneConfiguration newConfiguration);
+        @ElapsedRealtimeLong
+        long elapsedRealtimeMillis();
     }
 
     private static final String LOG_TAG = TimeZoneDetectorService.TAG;
-    private static final boolean DBG = false;
+    private static final boolean DBG = TimeZoneDetectorService.DBG;
 
     /**
      * The abstract score for an empty or invalid telephony suggestion.
@@ -166,10 +164,6 @@
     @NonNull
     private final Environment mEnvironment;
 
-    @GuardedBy("this")
-    @NonNull
-    private List<ConfigurationChangeListener> mConfigChangeListeners = new ArrayList<>();
-
     /**
      * A log that records the decisions / decision metadata that affected the device's time zone.
      * This is logged in bug reports to assist with debugging issues with detection.
@@ -183,7 +177,7 @@
      * to be stable.
      */
     @GuardedBy("this")
-    private ArrayMapWithHistory<Integer, QualifiedTelephonyTimeZoneSuggestion>
+    private final ArrayMapWithHistory<Integer, QualifiedTelephonyTimeZoneSuggestion>
             mTelephonySuggestionsBySlotIndex =
             new ArrayMapWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
 
@@ -192,18 +186,34 @@
      * detection then the latest suggestion is cleared.
      */
     @GuardedBy("this")
-    private ReferenceWithHistory<GeolocationTimeZoneSuggestion> mLatestGeoLocationSuggestion =
+    private final ReferenceWithHistory<GeolocationTimeZoneSuggestion> mLatestGeoLocationSuggestion =
             new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
 
     /**
      * The latest manual suggestion received.
      */
     @GuardedBy("this")
-    private ReferenceWithHistory<ManualTimeZoneSuggestion> mLatestManualSuggestion =
+    private final ReferenceWithHistory<ManualTimeZoneSuggestion> mLatestManualSuggestion =
             new ReferenceWithHistory<>(KEEP_SUGGESTION_HISTORY_SIZE);
 
     @GuardedBy("this")
-    private final List<Dumpable> mDumpables = new ArrayList<>();
+    @NonNull
+    private ConfigurationInternal mCurrentConfigurationInternal;
+
+    /**
+     * Whether telephony time zone detection fallback is currently enabled (when device config also
+     * allows).
+     *
+     * <p>This field is only actually used when telephony time zone fallback is supported, but the
+     * value is maintained even when it isn't supported as it can be turned on at any time via
+     * server flags. The reference time is the elapsed realtime when the mode last changed to help
+     * ordering between fallback mode switches and suggestions.
+     *
+     * <p>See {@link TimeZoneDetectorStrategy} for more information.
+     */
+    @GuardedBy("this")
+    @NonNull
+    private TimestampedValue<Boolean> mTelephonyTimeZoneFallbackEnabled;
 
     /**
      * Creates a new instance of {@link TimeZoneDetectorStrategyImpl}.
@@ -219,71 +229,23 @@
     @VisibleForTesting
     public TimeZoneDetectorStrategyImpl(@NonNull Environment environment) {
         mEnvironment = Objects.requireNonNull(environment);
-        mEnvironment.setConfigChangeListener(this::handleConfigChanged);
-    }
 
-    /**
-     * Adds a listener that allows the strategy to communicate with the surrounding service /
-     * internal. This must be called before the instance is used.
-     */
-    @Override
-    public synchronized void addConfigChangeListener(
-            @NonNull ConfigurationChangeListener listener) {
-        Objects.requireNonNull(listener);
-        mConfigChangeListeners.add(listener);
-    }
+        // Start with telephony fallback enabled.
+        mTelephonyTimeZoneFallbackEnabled =
+                new TimestampedValue<>(mEnvironment.elapsedRealtimeMillis(), true);
 
-    @Override
-    @NonNull
-    public ConfigurationInternal getConfigurationInternal(@UserIdInt int userId) {
-        return mEnvironment.getConfigurationInternal(userId);
-    }
-
-    @Override
-    @NonNull
-    public synchronized ConfigurationInternal getCurrentUserConfigurationInternal() {
-        int currentUserId = mEnvironment.getCurrentUserId();
-        return getConfigurationInternal(currentUserId);
-    }
-
-    @Override
-    public synchronized boolean updateConfiguration(@UserIdInt int userId,
-            @NonNull TimeZoneConfiguration requestedConfiguration) {
-        Objects.requireNonNull(requestedConfiguration);
-
-        TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
-                getConfigurationInternal(userId).createCapabilitiesAndConfig();
-        TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
-        TimeZoneConfiguration oldConfiguration = capabilitiesAndConfig.getConfiguration();
-
-        final TimeZoneConfiguration newConfiguration =
-                capabilities.tryApplyConfigChanges(oldConfiguration, requestedConfiguration);
-        if (newConfiguration == null) {
-            // The changes could not be made because the user's capabilities do not allow it.
-            return false;
+        synchronized (this) {
+            mEnvironment.setConfigurationInternalChangeListener(
+                    this::handleConfigurationInternalChanged);
+            mCurrentConfigurationInternal = mEnvironment.getCurrentUserConfigurationInternal();
         }
-
-        // Store the configuration / notify as needed. This will cause the mEnvironment to invoke
-        // handleConfigChanged() asynchronously.
-        mEnvironment.storeConfiguration(userId, newConfiguration);
-
-        String logMsg = "Configuration changed:"
-                + " oldConfiguration=" + oldConfiguration
-                + ", newConfiguration=" + newConfiguration;
-        mTimeZoneChangesLog.log(logMsg);
-        if (DBG) {
-            Slog.d(LOG_TAG, logMsg);
-        }
-        return true;
     }
 
     @Override
     public synchronized void suggestGeolocationTimeZone(
             @NonNull GeolocationTimeZoneSuggestion suggestion) {
 
-        int currentUserId = mEnvironment.getCurrentUserId();
-        ConfigurationInternal currentUserConfig =
-                mEnvironment.getConfigurationInternal(currentUserId);
+        ConfigurationInternal currentUserConfig = mCurrentConfigurationInternal;
         if (DBG) {
             Slog.d(LOG_TAG, "Geolocation suggestion received."
                     + " currentUserConfig=" + currentUserConfig
@@ -291,24 +253,31 @@
         }
         Objects.requireNonNull(suggestion);
 
-        if (currentUserConfig.getGeoDetectionEnabledBehavior()) {
-            // Only store a geolocation suggestion if geolocation detection is currently enabled.
-            // See also clearGeolocationSuggestionIfNeeded().
-            mLatestGeoLocationSuggestion.set(suggestion);
+        // Geolocation suggestions may be stored but not used during time zone detection if the
+        // configuration doesn't have geo time zone detection enabled. The caller is expected to
+        // withdraw a previous suggestion (i.e. submit an "uncertain" suggestion, when geo time zone
+        // detection is disabled.
 
-            // Now perform auto time zone detection. The new suggestion may be used to modify the
-            // time zone setting.
-            String reason = "New geolocation time zone suggested. suggestion=" + suggestion;
-            doAutoTimeZoneDetection(currentUserConfig, reason);
-        }
+        // The suggestion's "effective from" time is ignored: we currently assume suggestions
+        // are made in a sensible order and the most recent is always the best one to use.
+        mLatestGeoLocationSuggestion.set(suggestion);
+
+        // Update the mTelephonyTimeZoneFallbackEnabled state if needed: a certain suggestion
+        // will usually disable telephony fallback mode if it is currently enabled.
+        disableTelephonyFallbackIfNeeded();
+
+        // Now perform auto time zone detection. The new suggestion may be used to modify the
+        // time zone setting.
+        String reason = "New geolocation time zone suggested. suggestion=" + suggestion;
+        doAutoTimeZoneDetection(currentUserConfig, reason);
     }
 
     @Override
     public synchronized boolean suggestManualTimeZone(
             @UserIdInt int userId, @NonNull ManualTimeZoneSuggestion suggestion) {
 
-        int currentUserId = mEnvironment.getCurrentUserId();
-        if (userId != currentUserId) {
+        ConfigurationInternal currentUserConfig = mCurrentConfigurationInternal;
+        if (currentUserConfig.getUserId() != userId) {
             Slog.w(LOG_TAG, "Manual suggestion received but user != current user, userId=" + userId
                     + " suggestion=" + suggestion);
 
@@ -322,7 +291,7 @@
         String cause = "Manual time suggestion received: suggestion=" + suggestion;
 
         TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
-                getConfigurationInternal(userId).createCapabilitiesAndConfig();
+                currentUserConfig.createCapabilitiesAndConfig();
         TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
         if (capabilities.getSuggestManualTimeZoneCapability() != CAPABILITY_POSSESSED) {
             Slog.i(LOG_TAG, "User does not have the capability needed to set the time zone manually"
@@ -346,9 +315,7 @@
     public synchronized void suggestTelephonyTimeZone(
             @NonNull TelephonyTimeZoneSuggestion suggestion) {
 
-        int currentUserId = mEnvironment.getCurrentUserId();
-        ConfigurationInternal currentUserConfig =
-                mEnvironment.getConfigurationInternal(currentUserId);
+        ConfigurationInternal currentUserConfig = mCurrentConfigurationInternal;
         if (DBG) {
             Slog.d(LOG_TAG, "Telephony suggestion received. currentUserConfig=" + currentUserConfig
                     + " newSuggestion=" + suggestion);
@@ -363,18 +330,52 @@
         // Store the suggestion against the correct slotIndex.
         mTelephonySuggestionsBySlotIndex.put(suggestion.getSlotIndex(), scoredSuggestion);
 
-        // Now perform auto time zone detection. The new suggestion may be used to modify the time
-        // zone setting.
-        if (!currentUserConfig.getGeoDetectionEnabledBehavior()) {
-            String reason = "New telephony time zone suggested. suggestion=" + suggestion;
-            doAutoTimeZoneDetection(currentUserConfig, reason);
+        // Now perform auto time zone detection: the new suggestion might be used to modify the
+        // time zone setting.
+        String reason = "New telephony time zone suggested. suggestion=" + suggestion;
+        doAutoTimeZoneDetection(currentUserConfig, reason);
+    }
+
+    @Override
+    public synchronized void enableTelephonyTimeZoneFallback() {
+        // Only do any work if fallback is currently not enabled.
+        if (!mTelephonyTimeZoneFallbackEnabled.getValue()) {
+            ConfigurationInternal currentUserConfig = mCurrentConfigurationInternal;
+            if (DBG) {
+                Slog.d(LOG_TAG, "enableTelephonyTimeZoneFallbackMode"
+                        + ": currentUserConfig=" + currentUserConfig);
+            }
+
+            final boolean fallbackEnabled = true;
+            mTelephonyTimeZoneFallbackEnabled = new TimestampedValue<>(
+                    mEnvironment.elapsedRealtimeMillis(), fallbackEnabled);
+
+            // mTelephonyTimeZoneFallbackEnabled and mLatestGeoLocationSuggestion interact.
+            // If there is currently a certain geolocation suggestion, then the telephony fallback
+            // value needs to be considered after changing it.
+            // With the way that the mTelephonyTimeZoneFallbackEnabled time is currently chosen
+            // above, and the fact that geolocation suggestions should never have a time in the
+            // future, the following call will be a no-op, and telephony fallback will remain
+            // enabled. This comment / call is left as a reminder that it is possible for there to
+            // be a current, "certain" geolocation suggestion when this signal arrives and it is
+            // intentional that fallback stays enabled in this case. The choice to do this
+            // is mostly for symmetry WRT the case where fallback is enabled and an old "certain"
+            // geolocation is received; that would also leave telephony fallback enabled.
+            // This choice means that telephony fallback will remain enabled until a new "certain"
+            // geolocation suggestion is received. If, instead, the next geolocation is "uncertain",
+            // then telephony fallback will occur.
+            disableTelephonyFallbackIfNeeded();
+
+            if (currentUserConfig.isTelephonyFallbackSupported()) {
+                String reason = "enableTelephonyTimeZoneFallbackMode";
+                doAutoTimeZoneDetection(currentUserConfig, reason);
+            }
         }
     }
 
     @Override
     @NonNull
     public synchronized MetricsTimeZoneDetectorState generateMetricsState() {
-        int currentUserId = mEnvironment.getCurrentUserId();
         // Just capture one telephony suggestion: the one that would be used right now if telephony
         // detection is in use.
         QualifiedTelephonyTimeZoneSuggestion bestQualifiedTelephonySuggestion =
@@ -387,7 +388,7 @@
                 new OrdinalGenerator<>(new TimeZoneCanonicalizer());
         return MetricsTimeZoneDetectorState.create(
                 tzIdOrdinalGenerator,
-                getConfigurationInternal(currentUserId),
+                mCurrentConfigurationInternal,
                 mEnvironment.getDeviceTimeZone(),
                 getLatestManualSuggestion(),
                 telephonySuggestion,
@@ -427,9 +428,35 @@
             return;
         }
 
-        // Use the right suggestions based on the current configuration.
+        // Use the correct algorithm based on the user's current configuration. If it changes, then
+        // detection will be re-run.
         if (currentUserConfig.getGeoDetectionEnabledBehavior()) {
-            doGeolocationTimeZoneDetection(detectionReason);
+            boolean isGeoDetectionCertain = doGeolocationTimeZoneDetection(detectionReason);
+
+            // When geolocation detection is uncertain of the time zone, telephony detection
+            // can be used if telephony fallback is enabled and supported.
+            if (!isGeoDetectionCertain
+                    && mTelephonyTimeZoneFallbackEnabled.getValue()
+                    && currentUserConfig.isTelephonyFallbackSupported()) {
+
+                // This "only look at telephony if geolocation is uncertain" approach is
+                // deliberate to try to keep the logic simple and keep telephony and geolocation
+                // detection decoupled: when geolocation detection is in use, it is fully
+                // trusted and the most recent "certain" geolocation suggestion available will
+                // be used, even if the information it is based on is quite old.
+                // There could be newer telephony suggestions available, but telephony
+                // suggestions tend not to be withdrawn when they should be, and are based on
+                // combining information like MCC and NITZ signals, which could have been
+                // received at different times; thus it is hard to say what time the suggestion
+                // is actually "for" and reason clearly about ordering between telephony and
+                // geolocation suggestions.
+                //
+                // This approach is reliant on the location_time_zone_manager (and the location
+                // time zone providers it manages) correctly sending "uncertain" suggestions
+                // when the current location is unknown so that telephony fallback will actually be
+                // used.
+                doTelephonyTimeZoneDetection(detectionReason + ", telephony fallback mode");
+            }
         } else  {
             doTelephonyTimeZoneDetection(detectionReason);
         }
@@ -439,21 +466,29 @@
      * Detects the time zone using the latest available geolocation time zone suggestion, if one is
      * available. The outcome can be that this strategy becomes / remains un-opinionated and nothing
      * is set.
+     *
+     * @return true if geolocation time zone detection was certain of the time zone, false if it is
+     * uncertain
      */
     @GuardedBy("this")
-    private void doGeolocationTimeZoneDetection(@NonNull String detectionReason) {
+    private boolean doGeolocationTimeZoneDetection(@NonNull String detectionReason) {
         GeolocationTimeZoneSuggestion latestGeolocationSuggestion =
                 mLatestGeoLocationSuggestion.get();
         if (latestGeolocationSuggestion == null) {
-            return;
+            return false;
         }
 
         List<String> zoneIds = latestGeolocationSuggestion.getZoneIds();
-        if (zoneIds == null || zoneIds.isEmpty()) {
-            // This means the client has become uncertain about the time zone or it is certain there
-            // is no known zone. In either case we must leave the existing time zone setting as it
-            // is.
-            return;
+        if (zoneIds == null) {
+            // This means the originator of the suggestion is uncertain about the time zone. The
+            // existing time zone setting must be left as it is but detection can go on looking for
+            // a different answer elsewhere.
+            return false;
+        } else if (zoneIds.isEmpty()) {
+            // This means the originator is certain there is no time zone. The existing time zone
+            // setting must be left as it is and detection must not go looking for a different
+            // answer elsewhere.
+            return true;
         }
 
         // GeolocationTimeZoneSuggestion has no measure of quality. We assume all suggestions are
@@ -472,6 +507,34 @@
             zoneId = zoneIds.get(0);
         }
         setDeviceTimeZoneIfRequired(zoneId, detectionReason);
+        return true;
+    }
+
+    /**
+     * Sets the mTelephonyTimeZoneFallbackEnabled state to {@code false} if the latest geo
+     * suggestion is a "certain" suggestion that comes after the time when telephony fallback was
+     * enabled.
+     */
+    @GuardedBy("this")
+    private void disableTelephonyFallbackIfNeeded() {
+        GeolocationTimeZoneSuggestion suggestion = mLatestGeoLocationSuggestion.get();
+        boolean isLatestSuggestionCertain = suggestion != null && suggestion.getZoneIds() != null;
+        if (isLatestSuggestionCertain && mTelephonyTimeZoneFallbackEnabled.getValue()) {
+            // This transition ONLY changes mTelephonyTimeZoneFallbackEnabled from
+            // true -> false. See mTelephonyTimeZoneFallbackEnabled javadocs for details.
+
+            // Telephony fallback will be disabled after a "certain" suggestion is processed
+            // if and only if the location information it is based on is from after telephony
+            // fallback was enabled.
+            boolean latestSuggestionIsNewerThanFallbackEnabled =
+                    suggestion.getEffectiveFromElapsedMillis()
+                            > mTelephonyTimeZoneFallbackEnabled.getReferenceTimeMillis();
+            if (latestSuggestionIsNewerThanFallbackEnabled) {
+                final boolean fallbackEnabled = false;
+                mTelephonyTimeZoneFallbackEnabled = new TimestampedValue<>(
+                        mEnvironment.elapsedRealtimeMillis(), fallbackEnabled);
+            }
+        }
     }
 
     /**
@@ -593,45 +656,20 @@
         return findBestTelephonySuggestion();
     }
 
-    private synchronized void handleConfigChanged() {
-        if (DBG) {
-            Slog.d(LOG_TAG, "handleConfigChanged()");
-        }
-
-        clearGeolocationSuggestionIfNeeded();
-
-        for (ConfigurationChangeListener listener : mConfigChangeListeners) {
-            listener.onChange();
-        }
-    }
-
-    @GuardedBy("this")
-    private void clearGeolocationSuggestionIfNeeded() {
-        // This method is called whenever the user changes or the config for any user changes. We
-        // don't know what happened, so we capture the current user's config, check to see if we
-        // need to clear state associated with a previous user, and rerun detection.
-        int currentUserId = mEnvironment.getCurrentUserId();
+    private synchronized void handleConfigurationInternalChanged() {
         ConfigurationInternal currentUserConfig =
-                mEnvironment.getConfigurationInternal(currentUserId);
-
-        GeolocationTimeZoneSuggestion latestGeoLocationSuggestion =
-                mLatestGeoLocationSuggestion.get();
-        if (latestGeoLocationSuggestion != null
-                && !currentUserConfig.getGeoDetectionEnabledBehavior()) {
-            // The current user's config has geodetection disabled, so clear the latest suggestion.
-            // This is done to ensure we only ever keep a geolocation suggestion if the user has
-            // said it is ok to do so.
-            mLatestGeoLocationSuggestion.set(null);
-            mTimeZoneChangesLog.log(
-                    "clearGeolocationSuggestionIfNeeded: Cleared latest Geolocation suggestion.");
+                mEnvironment.getCurrentUserConfigurationInternal();
+        String logMsg = "handleConfigurationInternalChanged:"
+                + " oldConfiguration=" + mCurrentConfigurationInternal
+                + ", newConfiguration=" + currentUserConfig;
+        if (DBG) {
+            Slog.d(LOG_TAG, logMsg);
         }
+        mCurrentConfigurationInternal = currentUserConfig;
 
-        doAutoTimeZoneDetection(currentUserConfig, "clearGeolocationSuggestionIfNeeded()");
-    }
-
-    @Override
-    public synchronized void addDumpable(@NonNull Dumpable dumpable) {
-        mDumpables.add(dumpable);
+        // The configuration change may have changed available suggestions or the way suggestions
+        // are used, so re-run detection.
+        doAutoTimeZoneDetection(currentUserConfig, logMsg);
     }
 
     /**
@@ -642,15 +680,19 @@
         ipw.println("TimeZoneDetectorStrategy:");
 
         ipw.increaseIndent(); // level 1
-        int currentUserId = mEnvironment.getCurrentUserId();
-        ipw.println("mEnvironment.getCurrentUserId()=" + currentUserId);
-        ConfigurationInternal configuration = mEnvironment.getConfigurationInternal(currentUserId);
-        ipw.println("mEnvironment.getConfiguration(currentUserId)=" + configuration);
-        ipw.println("[Capabilities=" + configuration.createCapabilitiesAndConfig() + "]");
+        ipw.println("mCurrentConfigurationInternal=" + mCurrentConfigurationInternal);
+        ipw.println("[Capabilities=" + mCurrentConfigurationInternal.createCapabilitiesAndConfig()
+                + "]");
         ipw.println("mEnvironment.isDeviceTimeZoneInitialized()="
                 + mEnvironment.isDeviceTimeZoneInitialized());
         ipw.println("mEnvironment.getDeviceTimeZone()=" + mEnvironment.getDeviceTimeZone());
 
+        ipw.println("Misc state:");
+        ipw.increaseIndent(); // level 2
+        ipw.println("mTelephonyTimeZoneFallbackEnabled="
+                + formatDebugString(mTelephonyTimeZoneFallbackEnabled));
+        ipw.decreaseIndent(); // level 2
+
         ipw.println("Time zone change log:");
         ipw.increaseIndent(); // level 2
         mTimeZoneChangesLog.dump(ipw);
@@ -671,10 +713,6 @@
         mTelephonySuggestionsBySlotIndex.dump(ipw);
         ipw.decreaseIndent(); // level 2
         ipw.decreaseIndent(); // level 1
-
-        for (Dumpable dumpable : mDumpables) {
-            dumpable.dump(ipw, args);
-        }
     }
 
     /**
@@ -702,6 +740,11 @@
         return mLatestGeoLocationSuggestion.get();
     }
 
+    @VisibleForTesting
+    public synchronized boolean isTelephonyFallbackEnabledForTests() {
+        return mTelephonyTimeZoneFallbackEnabled.getValue();
+    }
+
     /**
      * A {@link TelephonyTimeZoneSuggestion} with additional qualifying metadata.
      */
@@ -751,4 +794,8 @@
                     + '}';
         }
     }
+
+    private static String formatDebugString(TimestampedValue<?> value) {
+        return value.getValue() + " @ " + Duration.ofMillis(value.getReferenceTimeMillis());
+    }
 }
diff --git a/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java b/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java
deleted file mode 100644
index 466a039..0000000
--- a/services/core/java/com/android/server/timezonedetector/location/ControllerImpl.java
+++ /dev/null
@@ -1,670 +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.server.timezonedetector.location;
-
-import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_PERMANENT_FAILURE;
-import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_SUGGESTION;
-import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_UNCERTAIN;
-
-import static com.android.server.timezonedetector.location.LocationTimeZoneManagerService.debugLog;
-import static com.android.server.timezonedetector.location.LocationTimeZoneManagerService.warnLog;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DESTROYED;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
-import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
-
-import android.annotation.DurationMillisLong;
-import android.annotation.ElapsedRealtimeLong;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.service.timezone.TimeZoneProviderEvent;
-import android.service.timezone.TimeZoneProviderSuggestion;
-import android.util.IndentingPrintWriter;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.server.timezonedetector.ConfigurationInternal;
-import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
-import com.android.server.timezonedetector.location.ThreadingDomain.SingleRunnableQueue;
-
-import java.time.Duration;
-import java.util.Objects;
-
-/**
- * A real implementation of {@link LocationTimeZoneProviderController} that supports a primary and a
- * secondary {@link LocationTimeZoneProvider}.
- *
- * <p>The primary is used until it fails or becomes uncertain. The secondary will then be started.
- * The controller will immediately make suggestions based on "certain" {@link
- * TimeZoneProviderEvent}s, i.e. events that demonstrate the provider is certain what the time zone
- * is. The controller will not make immediate suggestions based on "uncertain" events, giving
- * providers time to change their mind. This also gives the secondary provider time to initialize
- * when the primary becomes uncertain.
- */
-class ControllerImpl extends LocationTimeZoneProviderController {
-
-    @NonNull private final LocationTimeZoneProvider mPrimaryProvider;
-
-    @NonNull private final LocationTimeZoneProvider mSecondaryProvider;
-
-    @GuardedBy("mSharedLock")
-    // Non-null after initialize()
-    private ConfigurationInternal mCurrentUserConfiguration;
-
-    @GuardedBy("mSharedLock")
-    // Non-null after initialize()
-    private Environment mEnvironment;
-
-    @GuardedBy("mSharedLock")
-    // Non-null after initialize()
-    private Callback mCallback;
-
-    /** Indicates both providers have completed initialization. */
-    @GuardedBy("mSharedLock")
-    private boolean mProvidersInitialized;
-
-    /**
-     * Used for scheduling uncertainty timeouts, i.e after a provider has reported uncertainty.
-     * This timeout is not provider-specific: it is started when the controller becomes uncertain
-     * due to events it has received from one or other provider.
-     */
-    @NonNull private final SingleRunnableQueue mUncertaintyTimeoutQueue;
-
-    /** Contains the last suggestion actually made, if there is one. */
-    @GuardedBy("mSharedLock")
-    @Nullable
-    private GeolocationTimeZoneSuggestion mLastSuggestion;
-
-    ControllerImpl(@NonNull ThreadingDomain threadingDomain,
-            @NonNull LocationTimeZoneProvider primaryProvider,
-            @NonNull LocationTimeZoneProvider secondaryProvider) {
-        super(threadingDomain);
-        mUncertaintyTimeoutQueue = threadingDomain.createSingleRunnableQueue();
-        mPrimaryProvider = Objects.requireNonNull(primaryProvider);
-        mSecondaryProvider = Objects.requireNonNull(secondaryProvider);
-    }
-
-    @Override
-    void initialize(@NonNull Environment environment, @NonNull Callback callback) {
-        mThreadingDomain.assertCurrentThread();
-
-        synchronized (mSharedLock) {
-            debugLog("initialize()");
-            mEnvironment = Objects.requireNonNull(environment);
-            mCallback = Objects.requireNonNull(callback);
-            mCurrentUserConfiguration = environment.getCurrentUserConfigurationInternal();
-
-            LocationTimeZoneProvider.ProviderListener providerListener =
-                    ControllerImpl.this::onProviderStateChange;
-            mPrimaryProvider.initialize(providerListener);
-            mSecondaryProvider.initialize(providerListener);
-            mProvidersInitialized = true;
-
-            alterProvidersStartedStateIfRequired(
-                    null /* oldConfiguration */, mCurrentUserConfiguration);
-        }
-    }
-
-    @Override
-    void onConfigChanged() {
-        mThreadingDomain.assertCurrentThread();
-
-        synchronized (mSharedLock) {
-            debugLog("onConfigChanged()");
-
-            ConfigurationInternal oldConfig = mCurrentUserConfiguration;
-            ConfigurationInternal newConfig = mEnvironment.getCurrentUserConfigurationInternal();
-            mCurrentUserConfiguration = newConfig;
-
-            if (!newConfig.equals(oldConfig)) {
-                if (newConfig.getUserId() != oldConfig.getUserId()) {
-                    // If the user changed, stop the providers if needed. They may be re-started
-                    // for the new user immediately afterwards if their settings allow.
-                    debugLog("User changed. old=" + oldConfig.getUserId()
-                            + ", new=" + newConfig.getUserId() + ": Stopping providers");
-                    stopProviders();
-
-                    alterProvidersStartedStateIfRequired(null /* oldConfiguration */, newConfig);
-                } else {
-                    alterProvidersStartedStateIfRequired(oldConfig, newConfig);
-                }
-            }
-        }
-    }
-
-    @Override
-    boolean isUncertaintyTimeoutSet() {
-        return mUncertaintyTimeoutQueue.hasQueued();
-    }
-
-    @Override
-    @DurationMillisLong
-    long getUncertaintyTimeoutDelayMillis() {
-        return mUncertaintyTimeoutQueue.getQueuedDelayMillis();
-    }
-
-    @Override
-    void destroy() {
-        mThreadingDomain.assertCurrentThread();
-
-        synchronized (mSharedLock) {
-            stopProviders();
-            mPrimaryProvider.destroy();
-            mSecondaryProvider.destroy();
-        }
-    }
-
-    @GuardedBy("mSharedLock")
-    private void stopProviders() {
-        stopProviderIfStarted(mPrimaryProvider);
-        stopProviderIfStarted(mSecondaryProvider);
-
-        // By definition, if both providers are stopped, the controller is uncertain.
-        cancelUncertaintyTimeout();
-
-        // If a previous "certain" suggestion has been made, then a new "uncertain"
-        // suggestion must now be made to indicate the controller {does not / no longer has}
-        // an opinion and will not be sending further updates (until at least the providers are
-        // re-started).
-        if (mLastSuggestion != null && mLastSuggestion.getZoneIds() != null) {
-            GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
-                    mEnvironment.elapsedRealtimeMillis(), "Providers are stopping");
-            makeSuggestion(suggestion);
-        }
-    }
-
-    @GuardedBy("mSharedLock")
-    private void stopProviderIfStarted(@NonNull LocationTimeZoneProvider provider) {
-        if (provider.getCurrentState().isStarted()) {
-            stopProvider(provider);
-        }
-    }
-
-    @GuardedBy("mSharedLock")
-    private void stopProvider(@NonNull LocationTimeZoneProvider provider) {
-        ProviderState providerState = provider.getCurrentState();
-        switch (providerState.stateEnum) {
-            case PROVIDER_STATE_STOPPED: {
-                debugLog("No need to stop " + provider + ": already stopped");
-                break;
-            }
-            case PROVIDER_STATE_STARTED_INITIALIZING:
-            case PROVIDER_STATE_STARTED_CERTAIN:
-            case PROVIDER_STATE_STARTED_UNCERTAIN: {
-                debugLog("Stopping " + provider);
-                provider.stopUpdates();
-                break;
-            }
-            case PROVIDER_STATE_PERM_FAILED:
-            case PROVIDER_STATE_DESTROYED: {
-                debugLog("Unable to stop " + provider + ": it is terminated.");
-                break;
-            }
-            default: {
-                warnLog("Unknown provider state: " + provider);
-                break;
-            }
-        }
-    }
-
-    /**
-     * Sets the providers into the correct started/stopped state for the {@code newConfiguration}
-     * and, if there is a provider state change, makes any suggestions required to inform the
-     * downstream time zone detection code.
-     *
-     * <p>This is a utility method that exists to avoid duplicated logic for the various cases when
-     * provider started / stopped state may need to be set or changed, e.g. during initialization
-     * or when a new configuration has been received.
-     */
-    @GuardedBy("mSharedLock")
-    private void alterProvidersStartedStateIfRequired(
-            @Nullable ConfigurationInternal oldConfiguration,
-            @NonNull ConfigurationInternal newConfiguration) {
-
-        // Provider started / stopped states only need to be changed if geoDetectionEnabled has
-        // changed.
-        boolean oldGeoDetectionEnabled = oldConfiguration != null
-                && oldConfiguration.getGeoDetectionEnabledBehavior();
-        boolean newGeoDetectionEnabled = newConfiguration.getGeoDetectionEnabledBehavior();
-        if (oldGeoDetectionEnabled == newGeoDetectionEnabled) {
-            return;
-        }
-
-        // The check above ensures that the logic below only executes if providers are going from
-        // {started *} -> {stopped}, or {stopped} -> {started initializing}. If this changes in
-        // future and there could be {started *} -> {started *} cases, or cases where the provider
-        // can't be assumed to go straight to the {started initializing} state, then the logic below
-        // would need to cover extra conditions, for example:
-        // 1) If the primary is in {started uncertain}, the secondary should be started.
-        // 2) If (1), and the secondary instantly enters the {perm failed} state, the uncertainty
-        //    timeout started when the primary entered {started uncertain} should be cancelled.
-
-        if (newGeoDetectionEnabled) {
-            // Try to start the primary provider.
-            tryStartProvider(mPrimaryProvider, newConfiguration);
-
-            // The secondary should only ever be started if the primary now isn't started (i.e. it
-            // couldn't become {started initializing} because it is {perm failed}).
-            ProviderState newPrimaryState = mPrimaryProvider.getCurrentState();
-            if (!newPrimaryState.isStarted()) {
-                // If the primary provider is {perm failed} then the controller must try to start
-                // the secondary.
-                tryStartProvider(mSecondaryProvider, newConfiguration);
-
-                ProviderState newSecondaryState = mSecondaryProvider.getCurrentState();
-                if (!newSecondaryState.isStarted()) {
-                    // If both providers are {perm failed} then the controller immediately
-                    // becomes uncertain.
-                    GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
-                            mEnvironment.elapsedRealtimeMillis(),
-                            "Providers are failed:"
-                                    + " primary=" + mPrimaryProvider.getCurrentState()
-                                    + " secondary=" + mPrimaryProvider.getCurrentState());
-                    makeSuggestion(suggestion);
-                }
-            }
-        } else {
-            stopProviders();
-        }
-    }
-
-    @GuardedBy("mSharedLock")
-    private void tryStartProvider(@NonNull LocationTimeZoneProvider provider,
-            @NonNull ConfigurationInternal configuration) {
-        ProviderState providerState = provider.getCurrentState();
-        switch (providerState.stateEnum) {
-            case PROVIDER_STATE_STOPPED: {
-                debugLog("Enabling " + provider);
-                provider.startUpdates(configuration,
-                        mEnvironment.getProviderInitializationTimeout(),
-                        mEnvironment.getProviderInitializationTimeoutFuzz(),
-                        mEnvironment.getProviderEventFilteringAgeThreshold());
-                break;
-            }
-            case PROVIDER_STATE_STARTED_INITIALIZING:
-            case PROVIDER_STATE_STARTED_CERTAIN:
-            case PROVIDER_STATE_STARTED_UNCERTAIN: {
-                debugLog("No need to start " + provider + ": already started");
-                break;
-            }
-            case PROVIDER_STATE_PERM_FAILED:
-            case PROVIDER_STATE_DESTROYED: {
-                debugLog("Unable to start " + provider + ": it is terminated");
-                break;
-            }
-            default: {
-                throw new IllegalStateException("Unknown provider state:"
-                        + " provider=" + provider);
-            }
-        }
-    }
-
-    void onProviderStateChange(@NonNull ProviderState providerState) {
-        mThreadingDomain.assertCurrentThread();
-        LocationTimeZoneProvider provider = providerState.provider;
-        assertProviderKnown(provider);
-
-        synchronized (mSharedLock) {
-            // Ignore provider state changes during initialization. e.g. if the primary provider
-            // moves to PROVIDER_STATE_PERM_FAILED during initialization, the secondary will not
-            // be ready to take over yet.
-            if (!mProvidersInitialized) {
-                warnLog("onProviderStateChange: Ignoring provider state change because both"
-                        + " providers have not yet completed initialization."
-                        + " providerState=" + providerState);
-                return;
-            }
-
-            switch (providerState.stateEnum) {
-                case PROVIDER_STATE_STARTED_INITIALIZING:
-                case PROVIDER_STATE_STOPPED:
-                case PROVIDER_STATE_DESTROYED: {
-                    // This should never happen: entering initializing, stopped or destroyed are
-                    // triggered by the controller so and should not trigger a state change
-                    // callback.
-                    warnLog("onProviderStateChange: Unexpected state change for provider,"
-                            + " provider=" + provider);
-                    break;
-                }
-                case PROVIDER_STATE_STARTED_CERTAIN:
-                case PROVIDER_STATE_STARTED_UNCERTAIN: {
-                    // These are valid and only happen if an event is received while the provider is
-                    // started.
-                    debugLog("onProviderStateChange: Received notification of a state change while"
-                            + " started, provider=" + provider);
-                    handleProviderStartedStateChange(providerState);
-                    break;
-                }
-                case PROVIDER_STATE_PERM_FAILED: {
-                    debugLog("Received notification of permanent failure for"
-                            + " provider=" + provider);
-                    handleProviderFailedStateChange(providerState);
-                    break;
-                }
-                default: {
-                    warnLog("onProviderStateChange: Unexpected provider=" + provider);
-                }
-            }
-        }
-    }
-
-    private void assertProviderKnown(@NonNull LocationTimeZoneProvider provider) {
-        if (provider != mPrimaryProvider && provider != mSecondaryProvider) {
-            throw new IllegalArgumentException("Unknown provider: " + provider);
-        }
-    }
-
-    /**
-     * Called when a provider has reported that it has failed permanently.
-     */
-    @GuardedBy("mSharedLock")
-    private void handleProviderFailedStateChange(@NonNull ProviderState providerState) {
-        LocationTimeZoneProvider failedProvider = providerState.provider;
-        ProviderState primaryCurrentState = mPrimaryProvider.getCurrentState();
-        ProviderState secondaryCurrentState = mSecondaryProvider.getCurrentState();
-
-        // If a provider has failed, the other may need to be started.
-        if (failedProvider == mPrimaryProvider) {
-            if (!secondaryCurrentState.isTerminated()) {
-                // Try to start the secondary. This does nothing if the provider is already
-                // started, and will leave the provider in {started initializing} if the provider is
-                // stopped.
-                tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
-            }
-        } else if (failedProvider == mSecondaryProvider) {
-            // No-op: The secondary will only be active if the primary is uncertain or is
-            // terminated. So, there the primary should not need to be started when the secondary
-            // fails.
-            if (primaryCurrentState.stateEnum != PROVIDER_STATE_STARTED_UNCERTAIN
-                    && !primaryCurrentState.isTerminated()) {
-                warnLog("Secondary provider unexpected reported a failure:"
-                        + " failed provider=" + failedProvider.getName()
-                        + ", primary provider=" + mPrimaryProvider
-                        + ", secondary provider=" + mSecondaryProvider);
-            }
-        }
-
-        // If both providers are now terminated, the controller needs to tell the next component in
-        // the time zone detection process.
-        if (primaryCurrentState.isTerminated() && secondaryCurrentState.isTerminated()) {
-
-            // If both providers are newly terminated then the controller is uncertain by definition
-            // and it will never recover so it can send a suggestion immediately.
-            cancelUncertaintyTimeout();
-
-            // If both providers are now terminated, then a suggestion must be sent informing the
-            // time zone detector that there are no further updates coming in future.
-            GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
-                    mEnvironment.elapsedRealtimeMillis(),
-                    "Both providers are terminated:"
-                            + " primary=" + primaryCurrentState.provider
-                            + ", secondary=" + secondaryCurrentState.provider);
-            makeSuggestion(suggestion);
-        }
-    }
-
-    /**
-     * Called when a provider has changed state but just moved from one started state to another
-     * started state, usually as a result of a new {@link TimeZoneProviderEvent} being received.
-     * However, there are rare cases where the event can also be null.
-     */
-    @GuardedBy("mSharedLock")
-    private void handleProviderStartedStateChange(@NonNull ProviderState providerState) {
-        LocationTimeZoneProvider provider = providerState.provider;
-        TimeZoneProviderEvent event = providerState.event;
-        if (event == null) {
-            // Implicit uncertainty, i.e. where the provider is started, but a problem has been
-            // detected without having received an event. For example, if the process has detected
-            // the loss of a binder-based provider, or initialization took too long. This is treated
-            // the same as explicit uncertainty, i.e. where the provider has explicitly told this
-            // process it is uncertain.
-            long uncertaintyStartedElapsedMillis = mEnvironment.elapsedRealtimeMillis();
-            handleProviderUncertainty(provider, uncertaintyStartedElapsedMillis,
-                    "provider=" + provider + ", implicit uncertainty, event=null");
-            return;
-        }
-
-        if (!mCurrentUserConfiguration.getGeoDetectionEnabledBehavior()) {
-            // This should not happen: the provider should not be in an started state if the user
-            // does not have geodetection enabled.
-            warnLog("Provider=" + provider + " is started, but"
-                    + " currentUserConfiguration=" + mCurrentUserConfiguration
-                    + " suggests it shouldn't be.");
-        }
-
-        switch (event.getType()) {
-            case EVENT_TYPE_PERMANENT_FAILURE: {
-                // This shouldn't happen. A provider cannot be started and have this event type.
-                warnLog("Provider=" + provider + " is started, but event suggests it shouldn't be");
-                break;
-            }
-            case EVENT_TYPE_UNCERTAIN: {
-                long uncertaintyStartedElapsedMillis = event.getCreationElapsedMillis();
-                handleProviderUncertainty(provider, uncertaintyStartedElapsedMillis,
-                        "provider=" + provider + ", explicit uncertainty. event=" + event);
-                break;
-            }
-            case EVENT_TYPE_SUGGESTION: {
-                handleProviderSuggestion(provider, event);
-                break;
-            }
-            default: {
-                warnLog("Unknown eventType=" + event.getType());
-                break;
-            }
-        }
-    }
-
-    /**
-     * Called when a provider has become "certain" about the time zone(s).
-     */
-    @GuardedBy("mSharedLock")
-    private void handleProviderSuggestion(
-            @NonNull LocationTimeZoneProvider provider,
-            @NonNull TimeZoneProviderEvent providerEvent) {
-
-        // By definition, the controller is now certain.
-        cancelUncertaintyTimeout();
-
-        if (provider == mPrimaryProvider) {
-            stopProviderIfStarted(mSecondaryProvider);
-        }
-
-        TimeZoneProviderSuggestion providerSuggestion = providerEvent.getSuggestion();
-
-        // For the suggestion's effectiveFromElapsedMillis, use the time embedded in the provider's
-        // suggestion (which indicates the time when the provider detected the location used to
-        // establish the time zone).
-        //
-        // An alternative would be to use the current time or the providerEvent creation time, but
-        // this would hinder the ability for the time_zone_detector to judge which suggestions are
-        // based on newer information when comparing suggestions between different sources.
-        long effectiveFromElapsedMillis = providerSuggestion.getElapsedRealtimeMillis();
-        GeolocationTimeZoneSuggestion geoSuggestion =
-                GeolocationTimeZoneSuggestion.createCertainSuggestion(
-                        effectiveFromElapsedMillis, providerSuggestion.getTimeZoneIds());
-
-        String debugInfo = "Event received provider=" + provider
-                + ", providerEvent=" + providerEvent
-                + ", suggestionCreationTime=" + mEnvironment.elapsedRealtimeMillis();
-        geoSuggestion.addDebugInfo(debugInfo);
-        makeSuggestion(geoSuggestion);
-    }
-
-    @Override
-    public void dump(@NonNull IndentingPrintWriter ipw, @Nullable String[] args) {
-        synchronized (mSharedLock) {
-            ipw.println("LocationTimeZoneProviderController:");
-
-            ipw.increaseIndent(); // level 1
-            ipw.println("mCurrentUserConfiguration=" + mCurrentUserConfiguration);
-            ipw.println("providerInitializationTimeout="
-                    + mEnvironment.getProviderInitializationTimeout());
-            ipw.println("providerInitializationTimeoutFuzz="
-                    + mEnvironment.getProviderInitializationTimeoutFuzz());
-            ipw.println("uncertaintyDelay=" + mEnvironment.getUncertaintyDelay());
-            ipw.println("mLastSuggestion=" + mLastSuggestion);
-
-            ipw.println("Primary Provider:");
-            ipw.increaseIndent(); // level 2
-            mPrimaryProvider.dump(ipw, args);
-            ipw.decreaseIndent(); // level 2
-
-            ipw.println("Secondary Provider:");
-            ipw.increaseIndent(); // level 2
-            mSecondaryProvider.dump(ipw, args);
-            ipw.decreaseIndent(); // level 2
-
-            ipw.decreaseIndent(); // level 1
-        }
-    }
-
-    /** Sends an immediate suggestion, updating mLastSuggestion. */
-    @GuardedBy("mSharedLock")
-    private void makeSuggestion(@NonNull GeolocationTimeZoneSuggestion suggestion) {
-        debugLog("makeSuggestion: suggestion=" + suggestion);
-        mCallback.suggest(suggestion);
-        mLastSuggestion = suggestion;
-    }
-
-    /** Clears the uncertainty timeout. */
-    @GuardedBy("mSharedLock")
-    private void cancelUncertaintyTimeout() {
-        mUncertaintyTimeoutQueue.cancel();
-    }
-
-    /**
-     * Called when a provider has become "uncertain" about the time zone.
-     *
-     * <p>A provider is expected to report its uncertainty as soon as it becomes uncertain, as
-     * this enables the most flexibility for the controller to start other providers when there are
-     * multiple ones available. The controller is therefore responsible for deciding when to make a
-     * "uncertain" suggestion to the downstream time zone detector.
-     *
-     * <p>This method schedules an "uncertainty" timeout (if one isn't already scheduled) to be
-     * triggered later if nothing else preempts it. It can be preempted if the provider becomes
-     * certain (or does anything else that calls {@link
-     * #makeSuggestion(GeolocationTimeZoneSuggestion)}) within {@link
-     * Environment#getUncertaintyDelay()}. Preemption causes the scheduled
-     * "uncertainty" timeout to be cancelled. If the provider repeatedly sends uncertainty events
-     * within the uncertainty delay period, those events are effectively ignored (i.e. the timeout
-     * is not reset each time).
-     */
-    @GuardedBy("mSharedLock")
-    void handleProviderUncertainty(
-            @NonNull LocationTimeZoneProvider provider,
-            @ElapsedRealtimeLong long uncertaintyStartedElapsedMillis,
-            @NonNull String reason) {
-        Objects.requireNonNull(provider);
-
-        // Start the uncertainty timeout if needed to ensure the controller will eventually make an
-        // uncertain suggestion if no success event arrives in time to counteract it.
-        if (!mUncertaintyTimeoutQueue.hasQueued()) {
-            debugLog("Starting uncertainty timeout: reason=" + reason);
-
-            Duration uncertaintyDelay = mEnvironment.getUncertaintyDelay();
-            mUncertaintyTimeoutQueue.runDelayed(
-                    () -> onProviderUncertaintyTimeout(
-                            provider, uncertaintyStartedElapsedMillis, uncertaintyDelay),
-                    uncertaintyDelay.toMillis());
-        }
-
-        if (provider == mPrimaryProvider) {
-            // (Try to) start the secondary. It could already be started, or enabling might not
-            // succeed if the provider has previously reported it is perm failed. The uncertainty
-            // timeout (set above) is used to ensure that an uncertain suggestion will be made if
-            // the secondary cannot generate a success event in time.
-            tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
-        }
-    }
-
-    private void onProviderUncertaintyTimeout(
-            @NonNull LocationTimeZoneProvider provider,
-            @ElapsedRealtimeLong long uncertaintyStartedElapsedMillis,
-            @NonNull Duration uncertaintyDelay) {
-        mThreadingDomain.assertCurrentThread();
-
-        synchronized (mSharedLock) {
-            long afterUncertaintyTimeoutElapsedMillis = mEnvironment.elapsedRealtimeMillis();
-
-            // For the effectiveFromElapsedMillis suggestion property, use the
-            // uncertaintyStartedElapsedMillis. This is the time when the provider first reported
-            // uncertainty, i.e. before the uncertainty timeout.
-            //
-            // afterUncertaintyTimeoutElapsedMillis could be used instead, which is the time when
-            // the location_time_zone_manager finally confirms that the time zone was uncertain,
-            // but the suggestion property allows the information to be back-dated, which should
-            // help when comparing suggestions from different sources.
-            GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
-                    uncertaintyStartedElapsedMillis,
-                    "Uncertainty timeout triggered for " + provider.getName() + ":"
-                            + " primary=" + mPrimaryProvider
-                            + ", secondary=" + mSecondaryProvider
-                            + ", uncertaintyStarted="
-                            + Duration.ofMillis(uncertaintyStartedElapsedMillis)
-                            + ", afterUncertaintyTimeout="
-                            + Duration.ofMillis(afterUncertaintyTimeoutElapsedMillis)
-                            + ", uncertaintyDelay=" + uncertaintyDelay
-            );
-            makeSuggestion(suggestion);
-        }
-    }
-
-    @NonNull
-    private static GeolocationTimeZoneSuggestion createUncertainSuggestion(
-            @ElapsedRealtimeLong long effectiveFromElapsedMillis,
-            @NonNull String reason) {
-        GeolocationTimeZoneSuggestion suggestion =
-                GeolocationTimeZoneSuggestion.createUncertainSuggestion(
-                        effectiveFromElapsedMillis);
-        suggestion.addDebugInfo(reason);
-        return suggestion;
-    }
-
-    /**
-     * Clears recorded provider state changes (for use during tests).
-     */
-    void clearRecordedProviderStates() {
-        mThreadingDomain.assertCurrentThread();
-
-        synchronized (mSharedLock) {
-            mPrimaryProvider.clearRecordedStates();
-            mSecondaryProvider.clearRecordedStates();
-        }
-    }
-
-    /**
-     * Returns a snapshot of the current controller state for tests.
-     */
-    @NonNull
-    LocationTimeZoneManagerServiceState getStateForTests() {
-        mThreadingDomain.assertCurrentThread();
-
-        synchronized (mSharedLock) {
-            LocationTimeZoneManagerServiceState.Builder builder =
-                    new LocationTimeZoneManagerServiceState.Builder();
-            if (mLastSuggestion != null) {
-                builder.setLastSuggestion(mLastSuggestion);
-            }
-            builder.setPrimaryProviderStateChanges(mPrimaryProvider.getRecordedStates())
-                    .setSecondaryProviderStateChanges(mSecondaryProvider.getRecordedStates());
-            return builder.build();
-        }
-    }
-}
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
index c5c59ce..b23f11a 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerService.java
@@ -41,6 +41,7 @@
 import com.android.server.SystemService;
 import com.android.server.timezonedetector.Dumpable;
 import com.android.server.timezonedetector.ServiceConfigAccessor;
+import com.android.server.timezonedetector.ServiceConfigAccessorImpl;
 import com.android.server.timezonedetector.TimeZoneDetectorInternal;
 import com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderMetricsLogger;
 
@@ -77,18 +78,18 @@
         private LocationTimeZoneManagerService mService;
 
         @NonNull
-        private final ServiceConfigAccessor mServerConfigAccessor;
+        private final ServiceConfigAccessor mServiceConfigAccessor;
 
         public Lifecycle(@NonNull Context context) {
             super(Objects.requireNonNull(context));
-            mServerConfigAccessor = ServiceConfigAccessor.getInstance(context);
+            mServiceConfigAccessor = ServiceConfigAccessorImpl.getInstance(context);
         }
 
         @Override
         public void onStart() {
             Context context = getContext();
-            if (mServerConfigAccessor.isGeoTimeZoneDetectionFeatureSupportedInConfig()) {
-                mService = new LocationTimeZoneManagerService(context);
+            if (mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupportedInConfig()) {
+                mService = new LocationTimeZoneManagerService(context, mServiceConfigAccessor);
 
                 // The service currently exposes no LocalService or Binder API, but it extends
                 // Binder and is registered as a binder service so it can receive shell commands.
@@ -100,7 +101,7 @@
 
         @Override
         public void onBootPhase(@BootPhase int phase) {
-            if (mServerConfigAccessor.isGeoTimeZoneDetectionFeatureSupportedInConfig()) {
+            if (mServiceConfigAccessor.isGeoTimeZoneDetectionFeatureSupportedInConfig()) {
                 if (phase == PHASE_SYSTEM_SERVICES_READY) {
                     // The location service must be functioning after this boot phase.
                     mService.onSystemReady();
@@ -146,29 +147,31 @@
     /** The shared lock from {@link #mThreadingDomain}. */
     @NonNull private final Object mSharedLock;
 
-    @NonNull
-    private final ServiceConfigAccessor mServiceConfigAccessor;
+    @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
 
     // Lazily initialized. Can be null if the service has been stopped.
     @GuardedBy("mSharedLock")
-    private ControllerImpl mLocationTimeZoneDetectorController;
+    private LocationTimeZoneProviderController mLocationTimeZoneProviderController;
 
     // Lazily initialized. Can be null if the service has been stopped.
     @GuardedBy("mSharedLock")
-    private ControllerEnvironmentImpl mEnvironment;
+    private LocationTimeZoneProviderControllerEnvironmentImpl
+            mLocationTimeZoneProviderControllerEnvironment;
 
-    LocationTimeZoneManagerService(Context context) {
+    LocationTimeZoneManagerService(@NonNull Context context,
+            @NonNull ServiceConfigAccessor serviceConfigAccessor) {
         mContext = context.createAttributionContext(ATTRIBUTION_TAG);
         mHandler = FgThread.getHandler();
         mThreadingDomain = new HandlerThreadingDomain(mHandler);
         mSharedLock = mThreadingDomain.getLockObject();
-        mServiceConfigAccessor = ServiceConfigAccessor.getInstance(mContext);
+        mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
     }
 
     // According to the SystemService docs: All lifecycle methods are called from the system
     // server's main looper thread.
     void onSystemReady() {
-        mServiceConfigAccessor.addListener(this::handleServiceConfigurationChangedOnMainThread);
+        mServiceConfigAccessor.addLocationTimeZoneManagerConfigListener(
+                this::handleServiceConfigurationChangedOnMainThread);
     }
 
     private void handleServiceConfigurationChangedOnMainThread() {
@@ -187,7 +190,7 @@
             // Avoid starting the service if it is currently stopped. This is required because
             // server flags are used by tests to set behavior with the service stopped, and we don't
             // want the service being restarted after each flag is set.
-            if (mLocationTimeZoneDetectorController != null) {
+            if (mLocationTimeZoneProviderController != null) {
                 // Stop and start the service, waiting until completion.
                 stopOnDomainThread();
                 startOnDomainThread();
@@ -244,8 +247,7 @@
      * completion, it cannot be called from the {@code mThreadingDomain} thread.
      */
     void startWithTestProviders(@Nullable String testPrimaryProviderPackageName,
-            @Nullable String testSecondaryProviderPackageName,
-            boolean recordProviderStateChanges) {
+            @Nullable String testSecondaryProviderPackageName, boolean recordStateChanges) {
         enforceManageTimeZoneDetectorPermission();
 
         if (testPrimaryProviderPackageName == null && testSecondaryProviderPackageName == null) {
@@ -260,7 +262,7 @@
                         testPrimaryProviderPackageName);
                 mServiceConfigAccessor.setTestSecondaryLocationTimeZoneProviderPackageName(
                         testSecondaryProviderPackageName);
-                mServiceConfigAccessor.setRecordProviderStateChanges(recordProviderStateChanges);
+                mServiceConfigAccessor.setRecordStateChangesForTests(recordStateChanges);
                 startOnDomainThread();
             }
         }, BLOCKING_OP_WAIT_DURATION_MILLIS);
@@ -275,19 +277,32 @@
                 return;
             }
 
-            if (mLocationTimeZoneDetectorController == null) {
+            if (mLocationTimeZoneProviderController == null) {
                 LocationTimeZoneProvider primary = mPrimaryProviderConfig.createProvider();
                 LocationTimeZoneProvider secondary = mSecondaryProviderConfig.createProvider();
+                LocationTimeZoneProviderController.MetricsLogger metricsLogger =
+                        new LocationTimeZoneProviderController.MetricsLogger() {
+                            @Override
+                            public void onStateChange(
+                                    @LocationTimeZoneProviderController.State String state) {
+                                // TODO b/200279201 - wire this up to metrics code
+                                // No-op.
+                            }
+                        };
 
-                ControllerImpl controller =
-                        new ControllerImpl(mThreadingDomain, primary, secondary);
-                ControllerEnvironmentImpl environment = new ControllerEnvironmentImpl(
-                        mThreadingDomain, mServiceConfigAccessor, controller);
-                ControllerCallbackImpl callback = new ControllerCallbackImpl(mThreadingDomain);
+                boolean recordStateChanges = mServiceConfigAccessor.getRecordStateChangesForTests();
+                LocationTimeZoneProviderController controller =
+                        new LocationTimeZoneProviderController(mThreadingDomain, metricsLogger,
+                                primary, secondary, recordStateChanges);
+                LocationTimeZoneProviderControllerEnvironmentImpl environment =
+                        new LocationTimeZoneProviderControllerEnvironmentImpl(
+                                mThreadingDomain, mServiceConfigAccessor, controller);
+                LocationTimeZoneProviderControllerCallbackImpl callback =
+                        new LocationTimeZoneProviderControllerCallbackImpl(mThreadingDomain);
                 controller.initialize(environment, callback);
 
-                mEnvironment = environment;
-                mLocationTimeZoneDetectorController = controller;
+                mLocationTimeZoneProviderControllerEnvironment = environment;
+                mLocationTimeZoneProviderController = controller;
             }
         }
     }
@@ -309,11 +324,11 @@
         mThreadingDomain.assertCurrentThread();
 
         synchronized (mSharedLock) {
-            if (mLocationTimeZoneDetectorController != null) {
-                mLocationTimeZoneDetectorController.destroy();
-                mLocationTimeZoneDetectorController = null;
-                mEnvironment.destroy();
-                mEnvironment = null;
+            if (mLocationTimeZoneProviderController != null) {
+                mLocationTimeZoneProviderController.destroy();
+                mLocationTimeZoneProviderController = null;
+                mLocationTimeZoneProviderControllerEnvironment.destroy();
+                mLocationTimeZoneProviderControllerEnvironment = null;
 
                 // Clear test state so it won't be used the next time the service is started.
                 mServiceConfigAccessor.resetVolatileTestConfig();
@@ -335,8 +350,8 @@
 
         mThreadingDomain.postAndWait(() -> {
             synchronized (mSharedLock) {
-                if (mLocationTimeZoneDetectorController != null) {
-                    mLocationTimeZoneDetectorController.clearRecordedProviderStates();
+                if (mLocationTimeZoneProviderController != null) {
+                    mLocationTimeZoneProviderController.clearRecordedStates();
                 }
             }
         }, BLOCKING_OP_WAIT_DURATION_MILLIS);
@@ -354,10 +369,10 @@
             return mThreadingDomain.postAndWait(
                     () -> {
                         synchronized (mSharedLock) {
-                            if (mLocationTimeZoneDetectorController == null) {
+                            if (mLocationTimeZoneProviderController == null) {
                                 return null;
                             }
-                            return mLocationTimeZoneDetectorController.getStateForTests();
+                            return mLocationTimeZoneProviderController.getStateForTests();
                         }
                     },
                     BLOCKING_OP_WAIT_DURATION_MILLIS);
@@ -387,10 +402,10 @@
             mSecondaryProviderConfig.dump(ipw, args);
             ipw.decreaseIndent();
 
-            if (mLocationTimeZoneDetectorController == null) {
+            if (mLocationTimeZoneProviderController == null) {
                 ipw.println("{Stopped}");
             } else {
-                mLocationTimeZoneDetectorController.dump(ipw, args);
+                mLocationTimeZoneProviderController.dump(ipw, args);
             }
             ipw.decreaseIndent();
         }
@@ -444,10 +459,9 @@
             ProviderMetricsLogger providerMetricsLogger = new RealProviderMetricsLogger(mIndex);
             return new BinderLocationTimeZoneProvider(
                     providerMetricsLogger, mThreadingDomain, mName, proxy,
-                    mServiceConfigAccessor.getRecordProviderStateChanges());
+                    mServiceConfigAccessor.getRecordStateChangesForTests());
         }
 
-        @GuardedBy("mSharedLock")
         @Override
         public void dump(IndentingPrintWriter ipw, String[] args) {
             ipw.printf("getMode()=%s\n", getMode());
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerServiceState.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerServiceState.java
index 113926a..1f752f4 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerServiceState.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerServiceState.java
@@ -21,6 +21,7 @@
 
 import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
 import com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState;
+import com.android.server.timezonedetector.location.LocationTimeZoneProviderController.State;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -30,22 +31,35 @@
 /** A snapshot of the location time zone manager service's state for tests. */
 final class LocationTimeZoneManagerServiceState {
 
+    private final @State String mControllerState;
     @Nullable private final GeolocationTimeZoneSuggestion mLastSuggestion;
+    @NonNull private final List<@State String> mControllerStates;
     @NonNull private final List<ProviderState> mPrimaryProviderStates;
     @NonNull private final List<ProviderState> mSecondaryProviderStates;
 
     LocationTimeZoneManagerServiceState(@NonNull Builder builder) {
+        mControllerState = builder.mControllerState;
         mLastSuggestion = builder.mLastSuggestion;
+        mControllerStates = Objects.requireNonNull(builder.mControllerStates);
         mPrimaryProviderStates = Objects.requireNonNull(builder.mPrimaryProviderStates);
         mSecondaryProviderStates = Objects.requireNonNull(builder.mSecondaryProviderStates);
     }
 
+    public @State String getControllerState() {
+        return mControllerState;
+    }
+
     @Nullable
     public GeolocationTimeZoneSuggestion getLastSuggestion() {
         return mLastSuggestion;
     }
 
     @NonNull
+    public List<@State String> getControllerStates() {
+        return mControllerStates;
+    }
+
+    @NonNull
     public List<ProviderState> getPrimaryProviderStates() {
         return Collections.unmodifiableList(mPrimaryProviderStates);
     }
@@ -58,7 +72,9 @@
     @Override
     public String toString() {
         return "LocationTimeZoneManagerServiceState{"
-                + "mLastSuggestion=" + mLastSuggestion
+                + "mControllerState=" + mControllerState
+                + ", mLastSuggestion=" + mLastSuggestion
+                + ", mControllerStates=" + mControllerStates
                 + ", mPrimaryProviderStates=" + mPrimaryProviderStates
                 + ", mSecondaryProviderStates=" + mSecondaryProviderStates
                 + '}';
@@ -66,17 +82,31 @@
 
     static final class Builder {
 
+        private @State String mControllerState;
         private GeolocationTimeZoneSuggestion mLastSuggestion;
+        private List<@State String> mControllerStates;
         private List<ProviderState> mPrimaryProviderStates;
         private List<ProviderState> mSecondaryProviderStates;
 
         @NonNull
+        public Builder setControllerState(@State String stateEnum) {
+            mControllerState = stateEnum;
+            return this;
+        }
+
+        @NonNull
         Builder setLastSuggestion(@NonNull GeolocationTimeZoneSuggestion lastSuggestion) {
             mLastSuggestion = Objects.requireNonNull(lastSuggestion);
             return this;
         }
 
         @NonNull
+        public Builder setStateChanges(@NonNull List<@State String> states) {
+            mControllerStates = new ArrayList<>(states);
+            return this;
+        }
+
+        @NonNull
         Builder setPrimaryProviderStateChanges(@NonNull List<ProviderState> primaryProviderStates) {
             mPrimaryProviderStates = new ArrayList<>(primaryProviderStates);
             return this;
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
index 6c9e174..60bbea7 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneManagerShellCommand.java
@@ -40,6 +40,14 @@
 import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
 import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
 import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_UNKNOWN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_CERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_DESTROYED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_FAILED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_INITIALIZING;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_PROVIDERS_INITIALIZING;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_STOPPED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_UNCERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_UNKNOWN;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -55,6 +63,7 @@
 import com.android.internal.util.dump.DualDumpOutputStream;
 import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
 import com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.ProviderStateEnum;
+import com.android.server.timezonedetector.location.LocationTimeZoneProviderController.State;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -245,6 +254,7 @@
             outputStream.end(lastSuggestionToken);
         }
 
+        writeControllerStates(outputStream, state.getControllerStates());
         writeProviderStates(outputStream, state.getPrimaryProviderStates(),
                 "primary_provider_states",
                 LocationTimeZoneManagerServiceStateProto.PRIMARY_PROVIDER_STATES);
@@ -256,6 +266,37 @@
         return 0;
     }
 
+    private static void writeControllerStates(DualDumpOutputStream outputStream,
+            List<@State String> states) {
+        for (@State String state : states) {
+            outputStream.write("controller_states",
+                    LocationTimeZoneManagerServiceStateProto.CONTROLLER_STATES,
+                    convertControllerStateToProtoEnum(state));
+        }
+    }
+
+    private static int convertControllerStateToProtoEnum(@State String state) {
+        switch (state) {
+            case STATE_PROVIDERS_INITIALIZING:
+                return LocationTimeZoneManagerProto.CONTROLLER_STATE_PROVIDERS_INITIALIZING;
+            case STATE_STOPPED:
+                return LocationTimeZoneManagerProto.CONTROLLER_STATE_STOPPED;
+            case STATE_INITIALIZING:
+                return LocationTimeZoneManagerProto.CONTROLLER_STATE_INITIALIZING;
+            case STATE_UNCERTAIN:
+                return LocationTimeZoneManagerProto.CONTROLLER_STATE_UNCERTAIN;
+            case STATE_CERTAIN:
+                return LocationTimeZoneManagerProto.CONTROLLER_STATE_CERTAIN;
+            case STATE_FAILED:
+                return LocationTimeZoneManagerProto.CONTROLLER_STATE_FAILED;
+            case STATE_DESTROYED:
+                return LocationTimeZoneManagerProto.CONTROLLER_STATE_DESTROYED;
+            case STATE_UNKNOWN:
+            default:
+                return LocationTimeZoneManagerProto.CONTROLLER_STATE_UNKNOWN;
+        }
+    }
+
     private static void writeProviderStates(DualDumpOutputStream outputStream,
             List<LocationTimeZoneProvider.ProviderState> providerStates, String fieldName,
             long fieldId) {
diff --git a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
index fdb9c14..5d7730a 100644
--- a/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderController.java
@@ -16,31 +16,64 @@
 
 package com.android.server.timezonedetector.location;
 
+import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_PERMANENT_FAILURE;
+import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_SUGGESTION;
+import static android.service.timezone.TimeZoneProviderEvent.EVENT_TYPE_UNCERTAIN;
+
+import static com.android.server.timezonedetector.location.LocationTimeZoneManagerService.debugLog;
+import static com.android.server.timezonedetector.location.LocationTimeZoneManagerService.warnLog;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_DESTROYED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_PERM_FAILED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_CERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
+
 import android.annotation.DurationMillisLong;
 import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
-import android.os.Handler;
+import android.annotation.Nullable;
+import android.annotation.StringDef;
+import android.service.timezone.TimeZoneProviderEvent;
+import android.service.timezone.TimeZoneProviderSuggestion;
+import android.util.IndentingPrintWriter;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.timezonedetector.ConfigurationInternal;
 import com.android.server.timezonedetector.Dumpable;
 import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
-import com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState;
+import com.android.server.timezonedetector.ReferenceWithHistory;
+import com.android.server.timezonedetector.location.ThreadingDomain.SingleRunnableQueue;
 
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 import java.time.Duration;
+import java.util.ArrayList;
 import java.util.Objects;
 
 /**
- * An base class for the component responsible handling events from {@link
- * LocationTimeZoneProvider}s and synthesizing time zone ID suggestions for sending to the time zone
- * detector. This interface primarily exists to extract testable detection logic, i.e. with
- * a minimal number of threading considerations or dependencies on Android infrastructure.
+ * The component responsible handling events from {@link LocationTimeZoneProvider}s and synthesizing
+ * time zone ID suggestions for sending to the time zone detector.
+ *
+ * <p>This class primarily exists to extract unit-testable logic from the surrounding service class,
+ * i.e. with a minimal number of threading considerations or direct dependencies on Android
+ * infrastructure.
+ *
+ * <p>This class supports a primary and a secondary {@link LocationTimeZoneProvider}. The primary is
+ * used until it fails or becomes uncertain. The secondary will then be started. The controller will
+ * immediately make suggestions based on "certain" {@link TimeZoneProviderEvent}s, i.e. events that
+ * demonstrate the provider is certain what the time zone is. The controller will not make immediate
+ * suggestions based on "uncertain" events, giving providers time to change their mind. This also
+ * gives the secondary provider time to initialize when the primary becomes uncertain.
  *
  * <p>The controller interacts with the following components:
  * <ul>
- *     <li>The surrounding service, which calls {@link #initialize(Environment, Callback)} and
- *     {@link #onConfigChanged()}.</li>
- *     <li>The {@link Environment} through which obtains information it needs.</li>
+ *     <li>The surrounding service, which calls {@link #initialize(Environment, Callback)}.
+ *     <li>The {@link Environment} through which it obtains information it needs.</li>
  *     <li>The {@link Callback} through which it makes time zone suggestions.</li>
  *     <li>Any {@link LocationTimeZoneProvider} instances it owns, which communicate via the
  *     {@link LocationTimeZoneProvider.ProviderListener#onProviderStateChange(ProviderState)}
@@ -49,8 +82,9 @@
  *
  * <p>All incoming calls except for {@link
  * LocationTimeZoneProviderController#dump(android.util.IndentingPrintWriter, String[])} must be
- * made on the {@link Handler} thread of the {@link ThreadingDomain} passed to {@link
- * #LocationTimeZoneProviderController(ThreadingDomain)}.
+ * made on the {@link android.os.Handler} thread of the {@link ThreadingDomain} passed to {@link
+ * #LocationTimeZoneProviderController(ThreadingDomain, LocationTimeZoneProvider,
+ * LocationTimeZoneProvider)}.
  *
  * <p>Provider / controller integration notes:
  *
@@ -59,44 +93,718 @@
  * different from the certainty that there are no time zone IDs for the current location. A provider
  * can be certain about there being no time zone IDs for a location for good reason, e.g. for
  * disputed areas and oceans. Distinguishing uncertainty allows the controller to try other
- * providers (or give up), where as certainty means it should not.
+ * providers (or give up), whereas certainty means it should not.
  *
  * <p>A provider can fail permanently. A permanent failure will stop the provider until next
  * boot.
  */
-abstract class LocationTimeZoneProviderController implements Dumpable {
+class LocationTimeZoneProviderController implements Dumpable {
 
-    @NonNull protected final ThreadingDomain mThreadingDomain;
-    @NonNull protected final Object mSharedLock;
+    // String is used for easier logging / interpretation in bug reports Vs int.
+    @StringDef(prefix = "STATE_",
+            value = { STATE_UNKNOWN, STATE_PROVIDERS_INITIALIZING, STATE_STOPPED,
+                    STATE_INITIALIZING, STATE_UNCERTAIN, STATE_CERTAIN, STATE_FAILED,
+                    STATE_DESTROYED })
+    @Retention(RetentionPolicy.SOURCE)
+    @Target({ ElementType.TYPE_USE, ElementType.TYPE_PARAMETER })
+    @interface State {}
 
-    LocationTimeZoneProviderController(@NonNull ThreadingDomain threadingDomain) {
+    /** The state used for an uninitialized controller. */
+    static final @State String STATE_UNKNOWN = "UNKNOWN";
+
+    /**
+     * A state used while the location time zone providers are initializing. Enables detection
+     * / avoidance of unwanted fail-over behavior before both providers are initialized.
+     */
+    static final @State String STATE_PROVIDERS_INITIALIZING = "PROVIDERS_INITIALIZING";
+    /** An inactive state: Detection is disabled. */
+    static final @State String STATE_STOPPED = "STOPPED";
+    /** An active state: No suggestion has yet been made. */
+    static final @State String STATE_INITIALIZING = "INITIALIZING";
+    /** An active state: The last suggestion was "uncertain". */
+    static final @State String STATE_UNCERTAIN = "UNCERTAIN";
+    /** An active state: The last suggestion was "certain". */
+    static final @State String STATE_CERTAIN = "CERTAIN";
+    /** An inactive state: The location time zone providers have failed. */
+    static final @State String STATE_FAILED = "FAILED";
+    /** An inactive state: The controller is destroyed. */
+    static final @State String STATE_DESTROYED = "DESTROYED";
+
+    @NonNull private final ThreadingDomain mThreadingDomain;
+    @NonNull private final Object mSharedLock;
+    /**
+     * Used for scheduling uncertainty timeouts, i.e. after a provider has reported uncertainty.
+     * This timeout is not provider-specific: it is started when the controller becomes uncertain
+     * due to events it has received from one or other provider.
+     */
+    @NonNull private final SingleRunnableQueue mUncertaintyTimeoutQueue;
+
+    @NonNull private final MetricsLogger mMetricsLogger;
+    @NonNull private final LocationTimeZoneProvider mPrimaryProvider;
+    @NonNull private final LocationTimeZoneProvider mSecondaryProvider;
+
+    @GuardedBy("mSharedLock")
+    // Non-null after initialize()
+    private ConfigurationInternal mCurrentUserConfiguration;
+
+    @GuardedBy("mSharedLock")
+    // Non-null after initialize()
+    private Environment mEnvironment;
+
+    @GuardedBy("mSharedLock")
+    // Non-null after initialize()
+    private Callback mCallback;
+
+    /** Usually {@code false} but can be set to {@code true} to record state changes for testing. */
+    private final boolean mRecordStateChanges;
+
+    @GuardedBy("mSharedLock")
+    @NonNull
+    private final ArrayList<@State String> mRecordedStates = new ArrayList<>(0);
+
+    /**
+     * The current state. This is primarily for metrics / reporting of how long the controller
+     * spends active / inactive during a period. There is overlap with the provider states, but
+     * providers operate independently of each other, so this can help to understand how long the
+     * geo detection system overall was certain or uncertain when multiple providers might have been
+     * enabled concurrently.
+     */
+    @GuardedBy("mSharedLock")
+    private final ReferenceWithHistory<@State String> mState = new ReferenceWithHistory<>(10);
+
+    /** Contains the last suggestion actually made, if there is one. */
+    @GuardedBy("mSharedLock")
+    @Nullable
+    private GeolocationTimeZoneSuggestion mLastSuggestion;
+
+    LocationTimeZoneProviderController(@NonNull ThreadingDomain threadingDomain,
+            @NonNull MetricsLogger metricsLogger,
+            @NonNull LocationTimeZoneProvider primaryProvider,
+            @NonNull LocationTimeZoneProvider secondaryProvider,
+            boolean recordStateChanges) {
         mThreadingDomain = Objects.requireNonNull(threadingDomain);
         mSharedLock = threadingDomain.getLockObject();
+        mUncertaintyTimeoutQueue = threadingDomain.createSingleRunnableQueue();
+        mMetricsLogger = Objects.requireNonNull(metricsLogger);
+        mPrimaryProvider = Objects.requireNonNull(primaryProvider);
+        mSecondaryProvider = Objects.requireNonNull(secondaryProvider);
+        mRecordStateChanges = recordStateChanges;
+
+        synchronized (mSharedLock) {
+            mState.set(STATE_UNKNOWN);
+        }
     }
 
     /**
      * Called to initialize the controller during boot. Called once only.
      * {@link LocationTimeZoneProvider#initialize} must be called by this method.
      */
-    abstract void initialize(@NonNull Environment environment, @NonNull Callback callback);
+    void initialize(@NonNull Environment environment, @NonNull Callback callback) {
+        mThreadingDomain.assertCurrentThread();
+
+        synchronized (mSharedLock) {
+            debugLog("initialize()");
+            mEnvironment = Objects.requireNonNull(environment);
+            mCallback = Objects.requireNonNull(callback);
+            mCurrentUserConfiguration = environment.getCurrentUserConfigurationInternal();
+
+            LocationTimeZoneProvider.ProviderListener providerListener =
+                    LocationTimeZoneProviderController.this::onProviderStateChange;
+            setState(STATE_PROVIDERS_INITIALIZING);
+            mPrimaryProvider.initialize(providerListener);
+            mSecondaryProvider.initialize(providerListener);
+            setState(STATE_STOPPED);
+
+            alterProvidersStartedStateIfRequired(
+                    null /* oldConfiguration */, mCurrentUserConfiguration);
+        }
+    }
 
     /**
-     * Called when any settings or other device state that affect location-based time zone detection
-     * have changed. The receiver should call {@link
-     * Environment#getCurrentUserConfigurationInternal()} to get the current user's config. This
-     * call must be made on the {@link ThreadingDomain} handler thread.
+     * Called when the content of the {@link ConfigurationInternal} may have changed. The receiver
+     * should call {@link Environment#getCurrentUserConfigurationInternal()} to get the current
+     * user's config. This call must be made on the {@link ThreadingDomain} handler thread.
      */
-    abstract void onConfigChanged();
+    void onConfigurationInternalChanged() {
+        mThreadingDomain.assertCurrentThread();
+
+        synchronized (mSharedLock) {
+            debugLog("onConfigChanged()");
+
+            ConfigurationInternal oldConfig = mCurrentUserConfiguration;
+            ConfigurationInternal newConfig = mEnvironment.getCurrentUserConfigurationInternal();
+            mCurrentUserConfiguration = newConfig;
+
+            if (!newConfig.equals(oldConfig)) {
+                if (newConfig.getUserId() != oldConfig.getUserId()) {
+                    // If the user changed, stop the providers if needed. They may be re-started
+                    // for the new user immediately afterwards if their settings allow.
+                    debugLog("User changed. old=" + oldConfig.getUserId()
+                            + ", new=" + newConfig.getUserId() + ": Stopping providers");
+                    stopProviders();
+
+                    alterProvidersStartedStateIfRequired(null /* oldConfiguration */, newConfig);
+                } else {
+                    alterProvidersStartedStateIfRequired(oldConfig, newConfig);
+                }
+            }
+        }
+    }
 
     @VisibleForTesting
-    abstract boolean isUncertaintyTimeoutSet();
+    boolean isUncertaintyTimeoutSet() {
+        return mUncertaintyTimeoutQueue.hasQueued();
+    }
 
     @VisibleForTesting
     @DurationMillisLong
-    abstract long getUncertaintyTimeoutDelayMillis();
+    long getUncertaintyTimeoutDelayMillis() {
+        return mUncertaintyTimeoutQueue.getQueuedDelayMillis();
+    }
 
     /** Called if the geolocation time zone detection is being reconfigured. */
-    abstract void destroy();
+    void destroy() {
+        mThreadingDomain.assertCurrentThread();
+
+        synchronized (mSharedLock) {
+            stopProviders();
+
+            // Enter destroyed state.
+            mPrimaryProvider.destroy();
+            mSecondaryProvider.destroy();
+            setState(STATE_DESTROYED);
+        }
+    }
+
+    /**
+     * Updates {@link #mState} if needed, and performs all the record-keeping / callbacks associated
+     * with state changes.
+     */
+    @GuardedBy("mSharedLock")
+    private void setState(@State String state) {
+        if (!Objects.equals(mState.get(), state)) {
+            mState.set(state);
+            if (mRecordStateChanges) {
+                mRecordedStates.add(state);
+            }
+            mMetricsLogger.onStateChange(state);
+        }
+    }
+
+    @GuardedBy("mSharedLock")
+    private void stopProviders() {
+        stopProviderIfStarted(mPrimaryProvider);
+        stopProviderIfStarted(mSecondaryProvider);
+
+        // By definition, if both providers are stopped, the controller is uncertain.
+        cancelUncertaintyTimeout();
+
+        // If a previous "certain" suggestion has been made, then a new "uncertain"
+        // suggestion must now be made to indicate the controller {does not / no longer has}
+        // an opinion and will not be sending further updates (until at least the providers are
+        // re-started).
+        if (Objects.equals(mState.get(), STATE_CERTAIN)) {
+            GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
+                    mEnvironment.elapsedRealtimeMillis(), "Providers are stopping");
+            makeSuggestion(suggestion, STATE_UNCERTAIN);
+        }
+        setState(STATE_STOPPED);
+    }
+
+    @GuardedBy("mSharedLock")
+    private void stopProviderIfStarted(@NonNull LocationTimeZoneProvider provider) {
+        if (provider.getCurrentState().isStarted()) {
+            stopProvider(provider);
+        }
+    }
+
+    @GuardedBy("mSharedLock")
+    private void stopProvider(@NonNull LocationTimeZoneProvider provider) {
+        ProviderState providerState = provider.getCurrentState();
+        switch (providerState.stateEnum) {
+            case PROVIDER_STATE_STOPPED: {
+                debugLog("No need to stop " + provider + ": already stopped");
+                break;
+            }
+            case PROVIDER_STATE_STARTED_INITIALIZING:
+            case PROVIDER_STATE_STARTED_CERTAIN:
+            case PROVIDER_STATE_STARTED_UNCERTAIN: {
+                debugLog("Stopping " + provider);
+                provider.stopUpdates();
+                break;
+            }
+            case PROVIDER_STATE_PERM_FAILED:
+            case PROVIDER_STATE_DESTROYED: {
+                debugLog("Unable to stop " + provider + ": it is terminated.");
+                break;
+            }
+            default: {
+                warnLog("Unknown provider state: " + provider);
+                break;
+            }
+        }
+    }
+
+    /**
+     * Sets the providers into the correct started/stopped state for the {@code newConfiguration}
+     * and, if there is a provider state change, makes any suggestions required to inform the
+     * downstream time zone detection code.
+     *
+     * <p>This is a utility method that exists to avoid duplicated logic for the various cases when
+     * provider started / stopped state may need to be set or changed, e.g. during initialization
+     * or when a new configuration has been received.
+     */
+    @GuardedBy("mSharedLock")
+    private void alterProvidersStartedStateIfRequired(
+            @Nullable ConfigurationInternal oldConfiguration,
+            @NonNull ConfigurationInternal newConfiguration) {
+
+        // Provider started / stopped states only need to be changed if geoDetectionEnabled has
+        // changed.
+        boolean oldGeoDetectionEnabled = oldConfiguration != null
+                && oldConfiguration.getGeoDetectionEnabledBehavior();
+        boolean newGeoDetectionEnabled = newConfiguration.getGeoDetectionEnabledBehavior();
+        if (oldGeoDetectionEnabled == newGeoDetectionEnabled) {
+            return;
+        }
+
+        // The check above ensures that the logic below only executes if providers are going from
+        // {started *} -> {stopped}, or {stopped} -> {started initializing}. If this changes in
+        // future and there could be {started *} -> {started *} cases, or cases where the provider
+        // can't be assumed to go straight to the {started initializing} state, then the logic below
+        // would need to cover extra conditions, for example:
+        // 1) If the primary is in {started uncertain}, the secondary should be started.
+        // 2) If (1), and the secondary instantly enters the {perm failed} state, the uncertainty
+        //    timeout started when the primary entered {started uncertain} should be cancelled.
+
+        if (newGeoDetectionEnabled) {
+            setState(STATE_INITIALIZING);
+
+            // Try to start the primary provider.
+            tryStartProvider(mPrimaryProvider, newConfiguration);
+
+            // The secondary should only ever be started if the primary now isn't started (i.e. it
+            // couldn't become {started initializing} because it is {perm failed}).
+            ProviderState newPrimaryState = mPrimaryProvider.getCurrentState();
+            if (!newPrimaryState.isStarted()) {
+                // If the primary provider is {perm failed} then the controller must try to start
+                // the secondary.
+                tryStartProvider(mSecondaryProvider, newConfiguration);
+
+                ProviderState newSecondaryState = mSecondaryProvider.getCurrentState();
+                if (!newSecondaryState.isStarted()) {
+                    // If both providers are {perm failed} then the controller immediately
+                    // reports uncertain.
+                    GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
+                            mEnvironment.elapsedRealtimeMillis(),
+                            "Providers are failed:"
+                                    + " primary=" + mPrimaryProvider.getCurrentState()
+                                    + " secondary=" + mPrimaryProvider.getCurrentState());
+                    makeSuggestion(suggestion, STATE_FAILED);
+                }
+            }
+        } else {
+            stopProviders();
+        }
+    }
+
+    @GuardedBy("mSharedLock")
+    private void tryStartProvider(@NonNull LocationTimeZoneProvider provider,
+            @NonNull ConfigurationInternal configuration) {
+        ProviderState providerState = provider.getCurrentState();
+        switch (providerState.stateEnum) {
+            case PROVIDER_STATE_STOPPED: {
+                debugLog("Enabling " + provider);
+                provider.startUpdates(configuration,
+                        mEnvironment.getProviderInitializationTimeout(),
+                        mEnvironment.getProviderInitializationTimeoutFuzz(),
+                        mEnvironment.getProviderEventFilteringAgeThreshold());
+                break;
+            }
+            case PROVIDER_STATE_STARTED_INITIALIZING:
+            case PROVIDER_STATE_STARTED_CERTAIN:
+            case PROVIDER_STATE_STARTED_UNCERTAIN: {
+                debugLog("No need to start " + provider + ": already started");
+                break;
+            }
+            case PROVIDER_STATE_PERM_FAILED:
+            case PROVIDER_STATE_DESTROYED: {
+                debugLog("Unable to start " + provider + ": it is terminated");
+                break;
+            }
+            default: {
+                throw new IllegalStateException("Unknown provider state:"
+                        + " provider=" + provider);
+            }
+        }
+    }
+
+    void onProviderStateChange(@NonNull ProviderState providerState) {
+        mThreadingDomain.assertCurrentThread();
+        LocationTimeZoneProvider provider = providerState.provider;
+        assertProviderKnown(provider);
+
+        synchronized (mSharedLock) {
+            // Ignore provider state changes during initialization. e.g. if the primary provider
+            // moves to PROVIDER_STATE_PERM_FAILED during initialization, the secondary will not
+            // be ready to take over yet.
+            if (Objects.equals(mState.get(), STATE_PROVIDERS_INITIALIZING)) {
+                warnLog("onProviderStateChange: Ignoring provider state change because both"
+                        + " providers have not yet completed initialization."
+                        + " providerState=" + providerState);
+                return;
+            }
+
+            switch (providerState.stateEnum) {
+                case PROVIDER_STATE_STARTED_INITIALIZING:
+                case PROVIDER_STATE_STOPPED:
+                case PROVIDER_STATE_DESTROYED: {
+                    // This should never happen: entering initializing, stopped or destroyed are
+                    // triggered by the controller so and should not trigger a state change
+                    // callback.
+                    warnLog("onProviderStateChange: Unexpected state change for provider,"
+                            + " provider=" + provider);
+                    break;
+                }
+                case PROVIDER_STATE_STARTED_CERTAIN:
+                case PROVIDER_STATE_STARTED_UNCERTAIN: {
+                    // These are valid and only happen if an event is received while the provider is
+                    // started.
+                    debugLog("onProviderStateChange: Received notification of a state change while"
+                            + " started, provider=" + provider);
+                    handleProviderStartedStateChange(providerState);
+                    break;
+                }
+                case PROVIDER_STATE_PERM_FAILED: {
+                    debugLog("Received notification of permanent failure for"
+                            + " provider=" + provider);
+                    handleProviderFailedStateChange(providerState);
+                    break;
+                }
+                default: {
+                    warnLog("onProviderStateChange: Unexpected provider=" + provider);
+                }
+            }
+        }
+    }
+
+    private void assertProviderKnown(@NonNull LocationTimeZoneProvider provider) {
+        if (provider != mPrimaryProvider && provider != mSecondaryProvider) {
+            throw new IllegalArgumentException("Unknown provider: " + provider);
+        }
+    }
+
+    /**
+     * Called when a provider has reported that it has failed permanently.
+     */
+    @GuardedBy("mSharedLock")
+    private void handleProviderFailedStateChange(@NonNull ProviderState providerState) {
+        LocationTimeZoneProvider failedProvider = providerState.provider;
+        ProviderState primaryCurrentState = mPrimaryProvider.getCurrentState();
+        ProviderState secondaryCurrentState = mSecondaryProvider.getCurrentState();
+
+        // If a provider has failed, the other may need to be started.
+        if (failedProvider == mPrimaryProvider) {
+            if (!secondaryCurrentState.isTerminated()) {
+                // Try to start the secondary. This does nothing if the provider is already
+                // started, and will leave the provider in {started initializing} if the provider is
+                // stopped.
+                tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
+            }
+        } else if (failedProvider == mSecondaryProvider) {
+            // No-op: The secondary will only be active if the primary is uncertain or is
+            // terminated. So, there the primary should not need to be started when the secondary
+            // fails.
+            if (primaryCurrentState.stateEnum != PROVIDER_STATE_STARTED_UNCERTAIN
+                    && !primaryCurrentState.isTerminated()) {
+                warnLog("Secondary provider unexpected reported a failure:"
+                        + " failed provider=" + failedProvider.getName()
+                        + ", primary provider=" + mPrimaryProvider
+                        + ", secondary provider=" + mSecondaryProvider);
+            }
+        }
+
+        // If both providers are now terminated, the controller needs to tell the next component in
+        // the time zone detection process.
+        if (primaryCurrentState.isTerminated() && secondaryCurrentState.isTerminated()) {
+
+            // If both providers are newly terminated then the controller is uncertain by definition
+            // and it will never recover so it can send a suggestion immediately.
+            cancelUncertaintyTimeout();
+
+            // If both providers are now terminated, then a suggestion must be sent informing the
+            // time zone detector that there are no further updates coming in the future.
+            GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
+                    mEnvironment.elapsedRealtimeMillis(),
+                    "Both providers are terminated:"
+                            + " primary=" + primaryCurrentState.provider
+                            + ", secondary=" + secondaryCurrentState.provider);
+            makeSuggestion(suggestion, STATE_FAILED);
+        }
+    }
+
+    /**
+     * Called when a provider has changed state but just moved from one started state to another
+     * started state, usually as a result of a new {@link TimeZoneProviderEvent} being received.
+     * However, there are rare cases where the event can also be null.
+     */
+    @GuardedBy("mSharedLock")
+    private void handleProviderStartedStateChange(@NonNull ProviderState providerState) {
+        LocationTimeZoneProvider provider = providerState.provider;
+        TimeZoneProviderEvent event = providerState.event;
+        if (event == null) {
+            // Implicit uncertainty, i.e. where the provider is started, but a problem has been
+            // detected without having received an event. For example, if the process has detected
+            // the loss of a binder-based provider, or initialization took too long. This is treated
+            // the same as explicit uncertainty, i.e. where the provider has explicitly told this
+            // process it is uncertain.
+            long uncertaintyStartedElapsedMillis = mEnvironment.elapsedRealtimeMillis();
+            handleProviderUncertainty(provider, uncertaintyStartedElapsedMillis,
+                    "provider=" + provider + ", implicit uncertainty, event=null");
+            return;
+        }
+
+        if (!mCurrentUserConfiguration.getGeoDetectionEnabledBehavior()) {
+            // This should not happen: the provider should not be in an started state if the user
+            // does not have geodetection enabled.
+            warnLog("Provider=" + provider + " is started, but"
+                    + " currentUserConfiguration=" + mCurrentUserConfiguration
+                    + " suggests it shouldn't be.");
+        }
+
+        switch (event.getType()) {
+            case EVENT_TYPE_PERMANENT_FAILURE: {
+                // This shouldn't happen. A provider cannot be started and have this event type.
+                warnLog("Provider=" + provider + " is started, but event suggests it shouldn't be");
+                break;
+            }
+            case EVENT_TYPE_UNCERTAIN: {
+                long uncertaintyStartedElapsedMillis = event.getCreationElapsedMillis();
+                handleProviderUncertainty(provider, uncertaintyStartedElapsedMillis,
+                        "provider=" + provider + ", explicit uncertainty. event=" + event);
+                break;
+            }
+            case EVENT_TYPE_SUGGESTION: {
+                handleProviderSuggestion(provider, event);
+                break;
+            }
+            default: {
+                warnLog("Unknown eventType=" + event.getType());
+                break;
+            }
+        }
+    }
+
+    /**
+     * Called when a provider has become "certain" about the time zone(s).
+     */
+    @GuardedBy("mSharedLock")
+    private void handleProviderSuggestion(
+            @NonNull LocationTimeZoneProvider provider,
+            @NonNull TimeZoneProviderEvent providerEvent) {
+
+        // By definition, the controller is now certain.
+        cancelUncertaintyTimeout();
+
+        if (provider == mPrimaryProvider) {
+            stopProviderIfStarted(mSecondaryProvider);
+        }
+
+        TimeZoneProviderSuggestion providerSuggestion = providerEvent.getSuggestion();
+
+        // For the suggestion's effectiveFromElapsedMillis, use the time embedded in the provider's
+        // suggestion (which indicates the time when the provider detected the location used to
+        // establish the time zone).
+        //
+        // An alternative would be to use the current time or the providerEvent creation time, but
+        // this would hinder the ability for the time_zone_detector to judge which suggestions are
+        // based on newer information when comparing suggestions between different sources.
+        long effectiveFromElapsedMillis = providerSuggestion.getElapsedRealtimeMillis();
+        GeolocationTimeZoneSuggestion geoSuggestion =
+                GeolocationTimeZoneSuggestion.createCertainSuggestion(
+                        effectiveFromElapsedMillis, providerSuggestion.getTimeZoneIds());
+
+        String debugInfo = "Event received provider=" + provider
+                + ", providerEvent=" + providerEvent
+                + ", suggestionCreationTime=" + mEnvironment.elapsedRealtimeMillis();
+        geoSuggestion.addDebugInfo(debugInfo);
+        makeSuggestion(geoSuggestion, STATE_CERTAIN);
+    }
+
+    @Override
+    public void dump(@NonNull IndentingPrintWriter ipw, @Nullable String[] args) {
+        synchronized (mSharedLock) {
+            ipw.println("LocationTimeZoneProviderController:");
+
+            ipw.increaseIndent(); // level 1
+            ipw.println("mCurrentUserConfiguration=" + mCurrentUserConfiguration);
+            ipw.println("providerInitializationTimeout="
+                    + mEnvironment.getProviderInitializationTimeout());
+            ipw.println("providerInitializationTimeoutFuzz="
+                    + mEnvironment.getProviderInitializationTimeoutFuzz());
+            ipw.println("uncertaintyDelay=" + mEnvironment.getUncertaintyDelay());
+            ipw.println("mState=" + mState.get());
+            ipw.println("mLastSuggestion=" + mLastSuggestion);
+
+            ipw.println("State history:");
+            ipw.increaseIndent(); // level 2
+            mState.dump(ipw);
+            ipw.decreaseIndent(); // level 2
+
+            ipw.println("Primary Provider:");
+            ipw.increaseIndent(); // level 2
+            mPrimaryProvider.dump(ipw, args);
+            ipw.decreaseIndent(); // level 2
+
+            ipw.println("Secondary Provider:");
+            ipw.increaseIndent(); // level 2
+            mSecondaryProvider.dump(ipw, args);
+            ipw.decreaseIndent(); // level 2
+
+            ipw.decreaseIndent(); // level 1
+        }
+    }
+
+    /**
+     * Sends an immediate suggestion and enters a new state if needed. This method updates
+     * mLastSuggestion and changes mStateEnum / reports the new state for metrics.
+     */
+    @GuardedBy("mSharedLock")
+    private void makeSuggestion(@NonNull GeolocationTimeZoneSuggestion suggestion,
+            @State String newState) {
+        debugLog("makeSuggestion: suggestion=" + suggestion);
+        mCallback.suggest(suggestion);
+        mLastSuggestion = suggestion;
+        setState(newState);
+    }
+
+    /** Clears the uncertainty timeout. */
+    @GuardedBy("mSharedLock")
+    private void cancelUncertaintyTimeout() {
+        mUncertaintyTimeoutQueue.cancel();
+    }
+
+    /**
+     * Called when a provider has become "uncertain" about the time zone.
+     *
+     * <p>A provider is expected to report its uncertainty as soon as it becomes uncertain, as
+     * this enables the most flexibility for the controller to start other providers when there are
+     * multiple ones available. The controller is therefore responsible for deciding when to make a
+     * "uncertain" suggestion to the downstream time zone detector.
+     *
+     * <p>This method schedules an "uncertainty" timeout (if one isn't already scheduled) to be
+     * triggered later if nothing else preempts it. It can be preempted if the provider becomes
+     * certain (or does anything else that calls {@link
+     * #makeSuggestion(GeolocationTimeZoneSuggestion, String)}) within {@link
+     * Environment#getUncertaintyDelay()}. Preemption causes the scheduled
+     * "uncertainty" timeout to be cancelled. If the provider repeatedly sends uncertainty events
+     * within the uncertainty delay period, those events are effectively ignored (i.e. the timeout
+     * is not reset each time).
+     */
+    @GuardedBy("mSharedLock")
+    void handleProviderUncertainty(
+            @NonNull LocationTimeZoneProvider provider,
+            @ElapsedRealtimeLong long uncertaintyStartedElapsedMillis,
+            @NonNull String reason) {
+        Objects.requireNonNull(provider);
+
+        // Start the uncertainty timeout if needed to ensure the controller will eventually make an
+        // uncertain suggestion if no success event arrives in time to counteract it.
+        if (!mUncertaintyTimeoutQueue.hasQueued()) {
+            debugLog("Starting uncertainty timeout: reason=" + reason);
+
+            Duration uncertaintyDelay = mEnvironment.getUncertaintyDelay();
+            mUncertaintyTimeoutQueue.runDelayed(
+                    () -> onProviderUncertaintyTimeout(
+                            provider, uncertaintyStartedElapsedMillis, uncertaintyDelay),
+                    uncertaintyDelay.toMillis());
+        }
+
+        if (provider == mPrimaryProvider) {
+            // (Try to) start the secondary. It could already be started, or enabling might not
+            // succeed if the provider has previously reported it is perm failed. The uncertainty
+            // timeout (set above) is used to ensure that an uncertain suggestion will be made if
+            // the secondary cannot generate a success event in time.
+            tryStartProvider(mSecondaryProvider, mCurrentUserConfiguration);
+        }
+    }
+
+    private void onProviderUncertaintyTimeout(
+            @NonNull LocationTimeZoneProvider provider,
+            @ElapsedRealtimeLong long uncertaintyStartedElapsedMillis,
+            @NonNull Duration uncertaintyDelay) {
+        mThreadingDomain.assertCurrentThread();
+
+        synchronized (mSharedLock) {
+            long afterUncertaintyTimeoutElapsedMillis = mEnvironment.elapsedRealtimeMillis();
+
+            // For the effectiveFromElapsedMillis suggestion property, use the
+            // uncertaintyStartedElapsedMillis. This is the time when the provider first reported
+            // uncertainty, i.e. before the uncertainty timeout.
+            //
+            // afterUncertaintyTimeoutElapsedMillis could be used instead, which is the time when
+            // the location_time_zone_manager finally confirms that the time zone was uncertain,
+            // but the suggestion property allows the information to be back-dated, which should
+            // help when comparing suggestions from different sources.
+            GeolocationTimeZoneSuggestion suggestion = createUncertainSuggestion(
+                    uncertaintyStartedElapsedMillis,
+                    "Uncertainty timeout triggered for " + provider.getName() + ":"
+                            + " primary=" + mPrimaryProvider
+                            + ", secondary=" + mSecondaryProvider
+                            + ", uncertaintyStarted="
+                            + Duration.ofMillis(uncertaintyStartedElapsedMillis)
+                            + ", afterUncertaintyTimeout="
+                            + Duration.ofMillis(afterUncertaintyTimeoutElapsedMillis)
+                            + ", uncertaintyDelay=" + uncertaintyDelay
+            );
+            makeSuggestion(suggestion, STATE_UNCERTAIN);
+        }
+    }
+
+    @NonNull
+    private static GeolocationTimeZoneSuggestion createUncertainSuggestion(
+            @ElapsedRealtimeLong long effectiveFromElapsedMillis,
+            @NonNull String reason) {
+        GeolocationTimeZoneSuggestion suggestion =
+                GeolocationTimeZoneSuggestion.createUncertainSuggestion(
+                        effectiveFromElapsedMillis);
+        suggestion.addDebugInfo(reason);
+        return suggestion;
+    }
+
+    /**
+     * Clears recorded controller and provider state changes (for use during tests).
+     */
+    void clearRecordedStates() {
+        mThreadingDomain.assertCurrentThread();
+
+        synchronized (mSharedLock) {
+            mRecordedStates.clear();
+            mPrimaryProvider.clearRecordedStates();
+            mSecondaryProvider.clearRecordedStates();
+        }
+    }
+
+    /**
+     * Returns a snapshot of the current controller state for tests.
+     */
+    @NonNull
+    LocationTimeZoneManagerServiceState getStateForTests() {
+        mThreadingDomain.assertCurrentThread();
+
+        synchronized (mSharedLock) {
+            LocationTimeZoneManagerServiceState.Builder builder =
+                    new LocationTimeZoneManagerServiceState.Builder();
+            if (mLastSuggestion != null) {
+                builder.setLastSuggestion(mLastSuggestion);
+            }
+            builder.setControllerState(mState.get())
+                    .setStateChanges(mRecordedStates)
+                    .setPrimaryProviderStateChanges(mPrimaryProvider.getRecordedStates())
+                    .setSecondaryProviderStateChanges(mSecondaryProvider.getRecordedStates());
+            return builder.build();
+        }
+    }
 
     /**
      * Used by {@link LocationTimeZoneProviderController} to obtain information from the surrounding
@@ -168,4 +876,12 @@
          */
         abstract void suggest(@NonNull GeolocationTimeZoneSuggestion suggestion);
     }
+
+    /**
+     * Used by {@link LocationTimeZoneProviderController} to record events for metrics / telemetry.
+     */
+    interface MetricsLogger {
+        /** Called when the controller's state changes. */
+        void onStateChange(@State String stateEnum);
+    }
 }
diff --git a/services/core/java/com/android/server/timezonedetector/location/ControllerCallbackImpl.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerCallbackImpl.java
similarity index 82%
rename from services/core/java/com/android/server/timezonedetector/location/ControllerCallbackImpl.java
rename to services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerCallbackImpl.java
index 46eaad0..0c751aa 100644
--- a/services/core/java/com/android/server/timezonedetector/location/ControllerCallbackImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerCallbackImpl.java
@@ -24,11 +24,12 @@
 
 /**
  * The real implementation of {@link LocationTimeZoneProviderController.Callback} used by
- * {@link ControllerImpl} to interact with other server components.
+ * {@link LocationTimeZoneProviderController} to interact with other server components.
  */
-class ControllerCallbackImpl extends LocationTimeZoneProviderController.Callback {
+class LocationTimeZoneProviderControllerCallbackImpl
+        extends LocationTimeZoneProviderController.Callback {
 
-    ControllerCallbackImpl(@NonNull ThreadingDomain threadingDomain) {
+    LocationTimeZoneProviderControllerCallbackImpl(@NonNull ThreadingDomain threadingDomain) {
         super(threadingDomain);
     }
 
diff --git a/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerEnvironmentImpl.java
similarity index 72%
rename from services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
rename to services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerEnvironmentImpl.java
index 20fb61d..e7d16c8 100644
--- a/services/core/java/com/android/server/timezonedetector/location/ControllerEnvironmentImpl.java
+++ b/services/core/java/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerEnvironmentImpl.java
@@ -20,47 +20,46 @@
 import android.annotation.NonNull;
 import android.os.SystemClock;
 
-import com.android.server.LocalServices;
 import com.android.server.timezonedetector.ConfigurationChangeListener;
 import com.android.server.timezonedetector.ConfigurationInternal;
 import com.android.server.timezonedetector.ServiceConfigAccessor;
-import com.android.server.timezonedetector.TimeZoneDetectorInternal;
 
 import java.time.Duration;
 import java.util.Objects;
 
 /**
  * The real implementation of {@link LocationTimeZoneProviderController.Environment} used by
- * {@link ControllerImpl} to interact with other server components.
+ * {@link LocationTimeZoneProviderController} to interact with other server components.
  */
-class ControllerEnvironmentImpl extends LocationTimeZoneProviderController.Environment {
+class LocationTimeZoneProviderControllerEnvironmentImpl
+        extends LocationTimeZoneProviderController.Environment {
 
-    @NonNull private final TimeZoneDetectorInternal mTimeZoneDetectorInternal;
     @NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
-    @NonNull private final ConfigurationChangeListener mConfigurationChangeListener;
+    @NonNull private final ConfigurationChangeListener mConfigurationInternalChangeListener;
 
-    ControllerEnvironmentImpl(@NonNull ThreadingDomain threadingDomain,
+    LocationTimeZoneProviderControllerEnvironmentImpl(@NonNull ThreadingDomain threadingDomain,
             @NonNull ServiceConfigAccessor serviceConfigAccessor,
             @NonNull LocationTimeZoneProviderController controller) {
         super(threadingDomain);
         mServiceConfigAccessor = Objects.requireNonNull(serviceConfigAccessor);
-        mTimeZoneDetectorInternal = LocalServices.getService(TimeZoneDetectorInternal.class);
 
-        // Listen for configuration changes.
-        mConfigurationChangeListener = () -> mThreadingDomain.post(controller::onConfigChanged);
-        mTimeZoneDetectorInternal.addConfigurationListener(mConfigurationChangeListener);
+        // Listen for configuration internal changes.
+        mConfigurationInternalChangeListener =
+                () -> mThreadingDomain.post(controller::onConfigurationInternalChanged);
+        mServiceConfigAccessor.addConfigurationInternalChangeListener(
+                mConfigurationInternalChangeListener);
     }
 
-
     @Override
     void destroy() {
-        mTimeZoneDetectorInternal.removeConfigurationListener(mConfigurationChangeListener);
+        mServiceConfigAccessor.removeConfigurationInternalChangeListener(
+                mConfigurationInternalChangeListener);
     }
 
     @Override
     @NonNull
     ConfigurationInternal getCurrentUserConfigurationInternal() {
-        return mTimeZoneDetectorInternal.getCurrentUserConfigurationInternal();
+        return mServiceConfigAccessor.getCurrentUserConfigurationInternal();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index e9d5ad6..59b6a08 100755
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -470,14 +470,16 @@
     }
 
     private void stopUser(int userId) {
-        if (userId == mCurrentUserId) {
-            switchUser(ActivityManager.getCurrentUser());
-            return;
-        }
+        synchronized (mLock) {
+            if (userId == mCurrentUserId) {
+                switchUser(ActivityManager.getCurrentUser());
+                return;
+            }
 
-        releaseSessionOfUserLocked(userId);
-        unbindServiceOfUserLocked(userId);
-        mRunningProfiles.remove(userId);
+            releaseSessionOfUserLocked(userId);
+            unbindServiceOfUserLocked(userId);
+            mRunningProfiles.remove(userId);
+        }
     }
 
     private void startProfileLocked(int userId) {
@@ -3010,32 +3012,47 @@
         public void addHardwareInput(int deviceId, TvInputInfo inputInfo) {
             ensureHardwarePermission();
             ensureValidInput(inputInfo);
-            synchronized (mLock) {
-                mTvInputHardwareManager.addHardwareInput(deviceId, inputInfo);
-                addHardwareInputLocked(inputInfo);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    mTvInputHardwareManager.addHardwareInput(deviceId, inputInfo);
+                    addHardwareInputLocked(inputInfo);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
 
         public void addHdmiInput(int id, TvInputInfo inputInfo) {
             ensureHardwarePermission();
             ensureValidInput(inputInfo);
-            synchronized (mLock) {
-                mTvInputHardwareManager.addHdmiInput(id, inputInfo);
-                addHardwareInputLocked(inputInfo);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    mTvInputHardwareManager.addHdmiInput(id, inputInfo);
+                    addHardwareInputLocked(inputInfo);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
 
         public void removeHardwareInput(String inputId) {
             ensureHardwarePermission();
-            synchronized (mLock) {
-                ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
-                boolean removed = serviceState.hardwareInputMap.remove(inputId) != null;
-                if (removed) {
-                    buildTvInputListLocked(mUserId, null);
-                    mTvInputHardwareManager.removeHardwareInput(inputId);
-                } else {
-                    Slog.e(TAG, "failed to remove input " + inputId);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    ServiceState serviceState = getServiceStateLocked(mComponent, mUserId);
+                    boolean removed = serviceState.hardwareInputMap.remove(inputId) != null;
+                    if (removed) {
+                        buildTvInputListLocked(mUserId, null);
+                        mTvInputHardwareManager.removeHardwareInput(inputId);
+                    } else {
+                        Slog.e(TAG, "failed to remove input " + inputId);
+                    }
                 }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
             }
         }
     }
diff --git a/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java b/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
index cf212df..d0c6d13 100644
--- a/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
+++ b/services/core/java/com/android/server/tv/interactive/TvIAppManagerService.java
@@ -18,37 +18,55 @@
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
 import android.media.tv.interactive.ITvIAppClient;
 import android.media.tv.interactive.ITvIAppManager;
+import android.media.tv.interactive.ITvIAppManagerCallback;
 import android.media.tv.interactive.ITvIAppService;
 import android.media.tv.interactive.ITvIAppServiceCallback;
 import android.media.tv.interactive.ITvIAppSession;
 import android.media.tv.interactive.ITvIAppSessionCallback;
+import android.media.tv.interactive.TvIAppInfo;
 import android.media.tv.interactive.TvIAppService;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Process;
+import android.os.RemoteCallbackList;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.ArrayMap;
+import android.util.Slog;
 import android.util.SparseArray;
+import android.view.InputChannel;
 import android.view.Surface;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.PackageMonitor;
 import com.android.server.SystemService;
 import com.android.server.utils.Slogf;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+
 /**
  * This class provides a system service that manages interactive TV applications.
  */
@@ -68,6 +86,8 @@
     @GuardedBy("mLock")
     private final SparseArray<UserState> mUserStates = new SparseArray<>();
 
+    private final UserManager mUserManager;
+
     /**
      * Initializes the system service.
      * <p>
@@ -80,6 +100,149 @@
     public TvIAppManagerService(Context context) {
         super(context);
         mContext = context;
+        mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE);
+    }
+
+    @GuardedBy("mLock")
+    private void buildTvIAppServiceListLocked(int userId, String[] updatedPackages) {
+        UserState userState = getOrCreateUserStateLocked(userId);
+        userState.mPackageSet.clear();
+
+        if (DEBUG) {
+            Slogf.d(TAG, "buildTvIAppServiceListLocked");
+        }
+        PackageManager pm = mContext.getPackageManager();
+        List<ResolveInfo> services = pm.queryIntentServicesAsUser(
+                new Intent(TvIAppService.SERVICE_INTERFACE),
+                PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
+                userId);
+        List<TvIAppInfo> iAppList = new ArrayList<>();
+
+        for (ResolveInfo ri : services) {
+            ServiceInfo si = ri.serviceInfo;
+            // TODO: add BIND_TV_IAPP permission and check it here
+
+            ComponentName component = new ComponentName(si.packageName, si.name);
+            try {
+                TvIAppInfo info = new TvIAppInfo.Builder(mContext, component).build();
+                iAppList.add(info);
+            } catch (Exception e) {
+                Slogf.e(TAG, "failed to load TV IApp service " + si.name, e);
+                continue;
+            }
+            userState.mPackageSet.add(si.packageName);
+        }
+
+        // sort the iApp list by iApp service id
+        Collections.sort(iAppList, Comparator.comparing(TvIAppInfo::getId));
+        Map<String, TvIAppState> iAppMap = new HashMap<>();
+        ArrayMap<String, Integer> tiasAppCount = new ArrayMap<>(iAppMap.size());
+        for (TvIAppInfo info : iAppList) {
+            String iAppServiceId = info.getId();
+            if (DEBUG) {
+                Slogf.d(TAG, "add " + iAppServiceId);
+            }
+            // Running count of IApp for each IApp service
+            Integer count = tiasAppCount.get(iAppServiceId);
+            count = count == null ? 1 : count + 1;
+            tiasAppCount.put(iAppServiceId, count);
+            TvIAppState iAppState = userState.mIAppMap.get(iAppServiceId);
+            if (iAppState == null) {
+                iAppState = new TvIAppState();
+            }
+            iAppState.mInfo = info;
+            iAppState.mUid = getIAppUid(info);
+            iAppMap.put(iAppServiceId, iAppState);
+            iAppState.mIAppNumber = count;
+        }
+
+        for (String iAppServiceId : iAppMap.keySet()) {
+            if (!userState.mIAppMap.containsKey(iAppServiceId)) {
+                notifyIAppServiceAddedLocked(userState, iAppServiceId);
+            } else if (updatedPackages != null) {
+                // Notify the package updates
+                ComponentName component = iAppMap.get(iAppServiceId).mInfo.getComponent();
+                for (String updatedPackage : updatedPackages) {
+                    if (component.getPackageName().equals(updatedPackage)) {
+                        updateServiceConnectionLocked(component, userId);
+                        notifyIAppServiceUpdatedLocked(userState, iAppServiceId);
+                        break;
+                    }
+                }
+            }
+        }
+
+        for (String iAppServiceId : userState.mIAppMap.keySet()) {
+            if (!iAppMap.containsKey(iAppServiceId)) {
+                TvIAppInfo info = userState.mIAppMap.get(iAppServiceId).mInfo;
+                ServiceState serviceState = userState.mServiceStateMap.get(info.getComponent());
+                if (serviceState != null) {
+                    abortPendingCreateSessionRequestsLocked(serviceState, iAppServiceId, userId);
+                }
+                notifyIAppServiceRemovedLocked(userState, iAppServiceId);
+            }
+        }
+
+        userState.mIAppMap.clear();
+        userState.mIAppMap = iAppMap;
+    }
+
+    @GuardedBy("mLock")
+    private void notifyIAppServiceAddedLocked(UserState userState, String iAppServiceId) {
+        if (DEBUG) {
+            Slog.d(TAG, "notifyIAppServiceAddedLocked(iAppServiceId=" + iAppServiceId + ")");
+        }
+        int n = userState.mCallbacks.beginBroadcast();
+        for (int i = 0; i < n; ++i) {
+            try {
+                userState.mCallbacks.getBroadcastItem(i).onIAppServiceAdded(iAppServiceId);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "failed to report added IApp service to callback", e);
+            }
+        }
+        userState.mCallbacks.finishBroadcast();
+    }
+
+    @GuardedBy("mLock")
+    private void notifyIAppServiceRemovedLocked(UserState userState, String iAppServiceId) {
+        if (DEBUG) {
+            Slog.d(TAG, "notifyIAppServiceRemovedLocked(iAppServiceId=" + iAppServiceId + ")");
+        }
+        int n = userState.mCallbacks.beginBroadcast();
+        for (int i = 0; i < n; ++i) {
+            try {
+                userState.mCallbacks.getBroadcastItem(i).onIAppServiceRemoved(iAppServiceId);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "failed to report removed IApp service to callback", e);
+            }
+        }
+        userState.mCallbacks.finishBroadcast();
+    }
+
+    @GuardedBy("mLock")
+    private void notifyIAppServiceUpdatedLocked(UserState userState, String iAppServiceId) {
+        if (DEBUG) {
+            Slog.d(TAG, "notifyIAppServiceUpdatedLocked(iAppServiceId=" + iAppServiceId + ")");
+        }
+        int n = userState.mCallbacks.beginBroadcast();
+        for (int i = 0; i < n; ++i) {
+            try {
+                userState.mCallbacks.getBroadcastItem(i).onIAppServiceUpdated(iAppServiceId);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "failed to report updated IApp service to callback", e);
+            }
+        }
+        userState.mCallbacks.finishBroadcast();
+    }
+
+    private int getIAppUid(TvIAppInfo info) {
+        try {
+            return getContext().getPackageManager().getApplicationInfo(
+                    info.getServiceInfo().packageName, 0).uid;
+        } catch (PackageManager.NameNotFoundException e) {
+            Slogf.w(TAG, "Unable to get UID for  " + info, e);
+            return Process.INVALID_UID;
+        }
     }
 
     @Override
@@ -90,6 +253,273 @@
         publishBinderService(Context.TV_IAPP_SERVICE, new BinderService());
     }
 
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+            registerBroadcastReceivers();
+        } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
+            synchronized (mLock) {
+                buildTvIAppServiceListLocked(mCurrentUserId, null);
+            }
+        }
+    }
+
+    private void registerBroadcastReceivers() {
+        PackageMonitor monitor = new PackageMonitor() {
+            private void buildTvIAppServiceList(String[] packages) {
+                int userId = getChangingUserId();
+                synchronized (mLock) {
+                    if (mCurrentUserId == userId || mRunningProfiles.contains(userId)) {
+                        buildTvIAppServiceListLocked(userId, packages);
+                    }
+                }
+            }
+
+            @Override
+            public void onPackageUpdateFinished(String packageName, int uid) {
+                if (DEBUG) Slogf.d(TAG, "onPackageUpdateFinished(packageName=" + packageName + ")");
+                // This callback is invoked when the TV iApp service is reinstalled.
+                // In this case, isReplacing() always returns true.
+                buildTvIAppServiceList(new String[] { packageName });
+            }
+
+            @Override
+            public void onPackagesAvailable(String[] packages) {
+                if (DEBUG) {
+                    Slogf.d(TAG, "onPackagesAvailable(packages=" + Arrays.toString(packages) + ")");
+                }
+                // This callback is invoked when the media on which some packages exist become
+                // available.
+                if (isReplacing()) {
+                    buildTvIAppServiceList(packages);
+                }
+            }
+
+            @Override
+            public void onPackagesUnavailable(String[] packages) {
+                // This callback is invoked when the media on which some packages exist become
+                // unavailable.
+                if (DEBUG)  {
+                    Slogf.d(TAG, "onPackagesUnavailable(packages=" + Arrays.toString(packages)
+                            + ")");
+                }
+                if (isReplacing()) {
+                    buildTvIAppServiceList(packages);
+                }
+            }
+
+            @Override
+            public void onSomePackagesChanged() {
+                if (DEBUG) Slogf.d(TAG, "onSomePackagesChanged()");
+                if (isReplacing()) {
+                    if (DEBUG) Slogf.d(TAG, "Skipped building TV iApp list due to replacing");
+                    // When the package is updated, buildTvIAppServiceListLocked is called in other
+                    // methods instead.
+                    return;
+                }
+                buildTvIAppServiceList(null);
+            }
+
+            @Override
+            public boolean onPackageChanged(String packageName, int uid, String[] components) {
+                // The iApp list needs to be updated in any cases, regardless of whether
+                // it happened to the whole package or a specific component. Returning true so that
+                // the update can be handled in {@link #onSomePackagesChanged}.
+                return true;
+            }
+        };
+        monitor.register(mContext, null, UserHandle.ALL, true);
+
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+        intentFilter.addAction(Intent.ACTION_USER_REMOVED);
+        intentFilter.addAction(Intent.ACTION_USER_STARTED);
+        intentFilter.addAction(Intent.ACTION_USER_STOPPED);
+        mContext.registerReceiverAsUser(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                String action = intent.getAction();
+                if (Intent.ACTION_USER_SWITCHED.equals(action)) {
+                    switchUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+                } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
+                    removeUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0));
+                } else if (Intent.ACTION_USER_STARTED.equals(action)) {
+                    int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                    startUser(userId);
+                } else if (Intent.ACTION_USER_STOPPED.equals(action)) {
+                    int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
+                    stopUser(userId);
+                }
+            }
+        }, UserHandle.ALL, intentFilter, null, null);
+    }
+
+    private void switchUser(int userId) {
+        synchronized (mLock) {
+            if (mCurrentUserId == userId) {
+                return;
+            }
+            UserInfo userInfo = mUserManager.getUserInfo(userId);
+            if (userInfo.isProfile()) {
+                Slog.w(TAG, "cannot switch to a profile!");
+                return;
+            }
+
+            for (int runningId : mRunningProfiles) {
+                releaseSessionOfUserLocked(runningId);
+                unbindServiceOfUserLocked(runningId);
+            }
+            mRunningProfiles.clear();
+            releaseSessionOfUserLocked(mCurrentUserId);
+            unbindServiceOfUserLocked(mCurrentUserId);
+
+            mCurrentUserId = userId;
+            buildTvIAppServiceListLocked(userId, null);
+        }
+    }
+
+    private void removeUser(int userId) {
+        synchronized (mLock) {
+            UserState userState = getUserStateLocked(userId);
+            if (userState == null) {
+                return;
+            }
+            // Release all created sessions.
+            for (SessionState state : userState.mSessionStateMap.values()) {
+                if (state.mSession != null) {
+                    try {
+                        state.mSession.release();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "error in release", e);
+                    }
+                }
+            }
+            userState.mSessionStateMap.clear();
+
+            // Unregister all callbacks and unbind all services.
+            for (ServiceState serviceState : userState.mServiceStateMap.values()) {
+                if (serviceState.mService != null) {
+                    if (serviceState.mCallback != null) {
+                        try {
+                            serviceState.mService.unregisterCallback(serviceState.mCallback);
+                        } catch (RemoteException e) {
+                            Slog.e(TAG, "error in unregisterCallback", e);
+                        }
+                    }
+                    mContext.unbindService(serviceState.mConnection);
+                }
+            }
+            userState.mServiceStateMap.clear();
+
+            // Clear everything else.
+            userState.mIAppMap.clear();
+            userState.mPackageSet.clear();
+            userState.mClientStateMap.clear();
+            userState.mCallbacks.kill();
+
+            mRunningProfiles.remove(userId);
+            mUserStates.remove(userId);
+
+            if (userId == mCurrentUserId) {
+                switchUser(UserHandle.USER_SYSTEM);
+            }
+        }
+    }
+
+    private void startUser(int userId) {
+        synchronized (mLock) {
+            if (userId == mCurrentUserId || mRunningProfiles.contains(userId)) {
+                // user already started
+                return;
+            }
+            UserInfo userInfo = mUserManager.getUserInfo(userId);
+            UserInfo parentInfo = mUserManager.getProfileParent(userId);
+            if (userInfo.isProfile()
+                    && parentInfo != null
+                    && parentInfo.id == mCurrentUserId) {
+                // only the children of the current user can be started in background
+                startProfileLocked(userId);
+            }
+        }
+    }
+
+    private void stopUser(int userId) {
+        synchronized (mLock) {
+            if (userId == mCurrentUserId) {
+                switchUser(ActivityManager.getCurrentUser());
+                return;
+            }
+
+            releaseSessionOfUserLocked(userId);
+            unbindServiceOfUserLocked(userId);
+            mRunningProfiles.remove(userId);
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void startProfileLocked(int userId) {
+        mRunningProfiles.add(userId);
+        buildTvIAppServiceListLocked(userId, null);
+    }
+
+    @GuardedBy("mLock")
+    private void releaseSessionOfUserLocked(int userId) {
+        UserState userState = getUserStateLocked(userId);
+        if (userState == null) {
+            return;
+        }
+        List<SessionState> sessionStatesToRelease = new ArrayList<>();
+        for (SessionState sessionState : userState.mSessionStateMap.values()) {
+            if (sessionState.mSession != null) {
+                sessionStatesToRelease.add(sessionState);
+            }
+        }
+        for (SessionState sessionState : sessionStatesToRelease) {
+            try {
+                sessionState.mSession.release();
+            } catch (RemoteException e) {
+                Slog.e(TAG, "error in release", e);
+            }
+            clearSessionAndNotifyClientLocked(sessionState);
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void unbindServiceOfUserLocked(int userId) {
+        UserState userState = getUserStateLocked(userId);
+        if (userState == null) {
+            return;
+        }
+        for (Iterator<ComponentName> it = userState.mServiceStateMap.keySet().iterator();
+                it.hasNext(); ) {
+            ComponentName component = it.next();
+            ServiceState serviceState = userState.mServiceStateMap.get(component);
+            if (serviceState != null && serviceState.mSessionTokens.isEmpty()) {
+                if (serviceState.mCallback != null) {
+                    try {
+                        serviceState.mService.unregisterCallback(serviceState.mCallback);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "error in unregisterCallback", e);
+                    }
+                }
+                mContext.unbindService(serviceState.mConnection);
+                it.remove();
+            }
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void clearSessionAndNotifyClientLocked(SessionState state) {
+        if (state.mClient != null) {
+            try {
+                state.mClient.onSessionReleased(state.mSeq);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "error in onSessionReleased", e);
+            }
+        }
+        removeSessionStateLocked(state.mSessionToken, state.mUserId);
+    }
+
     private SessionState getSessionState(IBinder sessionToken) {
         // TODO: implement user state and get session from it.
         return null;
@@ -150,6 +580,25 @@
     private final class BinderService extends ITvIAppManager.Stub {
 
         @Override
+        public List<TvIAppInfo> getTvIAppServiceList(int userId) {
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+                    Binder.getCallingUid(), userId, "getTvIAppServiceList");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    UserState userState = getOrCreateUserStateLocked(resolvedUserId);
+                    List<TvIAppInfo> iAppList = new ArrayList<>();
+                    for (TvIAppState state : userState.mIAppMap.values()) {
+                        iAppList.add(state.mInfo);
+                    }
+                    return iAppList;
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
         public void createSession(final ITvIAppClient client, final String iAppServiceId, int type,
                 int seq, int userId) {
             final int callingUid = Binder.getCallingUid();
@@ -163,14 +612,14 @@
                     if (userId != mCurrentUserId && !mRunningProfiles.contains(userId)) {
                         // Only current user and its running profiles can create sessions.
                         // Let the client get onConnectionFailed callback for this case.
-                        sendSessionTokenToClientLocked(client, iAppServiceId, null, seq);
+                        sendSessionTokenToClientLocked(client, iAppServiceId, null, null, seq);
                         return;
                     }
                     UserState userState = getOrCreateUserStateLocked(resolvedUserId);
                     TvIAppState iAppState = userState.mIAppMap.get(iAppServiceId);
                     if (iAppState == null) {
                         Slogf.w(TAG, "Failed to find state for iAppServiceId=" + iAppServiceId);
-                        sendSessionTokenToClientLocked(client, iAppServiceId, null, seq);
+                        sendSessionTokenToClientLocked(client, iAppServiceId, null, null, seq);
                         return;
                     }
                     ServiceState serviceState =
@@ -183,7 +632,7 @@
                     }
                     // Send a null token immediately while reconnecting.
                     if (serviceState.mReconnecting) {
-                        sendSessionTokenToClientLocked(client, iAppServiceId, null, seq);
+                        sendSessionTokenToClientLocked(client, iAppServiceId, null, null, seq);
                         return;
                     }
 
@@ -294,13 +743,47 @@
                 Binder.restoreCallingIdentity(identity);
             }
         }
+
+        @Override
+        public void registerCallback(final ITvIAppManagerCallback callback, int userId) {
+            int callingPid = Binder.getCallingPid();
+            int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, userId,
+                    "registerCallback");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    final UserState userState = getOrCreateUserStateLocked(resolvedUserId);
+                    if (!userState.mCallbacks.register(callback)) {
+                        Slog.e(TAG, "client process has already died");
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void unregisterCallback(ITvIAppManagerCallback callback, int userId) {
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(),
+                    Binder.getCallingUid(), userId, "unregisterCallback");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    UserState userState = getOrCreateUserStateLocked(resolvedUserId);
+                    userState.mCallbacks.unregister(callback);
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
     }
 
     @GuardedBy("mLock")
     private void sendSessionTokenToClientLocked(ITvIAppClient client, String iAppServiceId,
-            IBinder sessionToken, int seq) {
+            IBinder sessionToken, InputChannel channel, int seq) {
         try {
-            client.onSessionCreated(iAppServiceId, sessionToken, seq);
+            client.onSessionCreated(iAppServiceId, sessionToken, channel, seq);
         } catch (RemoteException e) {
             Slogf.e(TAG, "error in onSessionCreated", e);
         }
@@ -315,20 +798,23 @@
             Slogf.d(TAG, "createSessionInternalLocked(iAppServiceId="
                     + sessionState.mIAppServiceId + ")");
         }
+        InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString());
 
         // Set up a callback to send the session token.
-        ITvIAppSessionCallback callback = new SessionCallback(sessionState);
+        ITvIAppSessionCallback callback = new SessionCallback(sessionState, channels);
 
         boolean created = true;
         // Create a session. When failed, send a null token immediately.
         try {
-            service.createSession(callback, sessionState.mIAppServiceId, sessionState.mType);
+            service.createSession(
+                    channels[1], callback, sessionState.mIAppServiceId, sessionState.mType);
         } catch (RemoteException e) {
             Slogf.e(TAG, "error in createSession", e);
             sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mIAppServiceId, null,
-                    sessionState.mSeq);
+                    null, sessionState.mSeq);
             created = false;
         }
+        channels[1].dispose();
         return created;
     }
 
@@ -401,7 +887,7 @@
         for (SessionState sessionState : sessionsToAbort) {
             removeSessionStateLocked(sessionState.mSessionToken, sessionState.mUserId);
             sendSessionTokenToClientLocked(sessionState.mClient,
-                    sessionState.mIAppServiceId, null, sessionState.mSeq);
+                    sessionState.mIAppServiceId, null, null, sessionState.mSeq);
         }
         updateServiceConnectionLocked(serviceState.mComponent, userId);
     }
@@ -462,19 +948,24 @@
         // A mapping from the token of a TV IApp session to its state.
         private final Map<IBinder, SessionState> mSessionStateMap = new HashMap<>();
 
+        // A set of all TV IApp service packages.
+        private final Set<String> mPackageSet = new HashSet<>();
+
+        // A list of callbacks.
+        private final RemoteCallbackList<ITvIAppManagerCallback> mCallbacks =
+                new RemoteCallbackList<>();
+
         private UserState(int userId) {
             mUserId = userId;
         }
     }
 
     private static final class TvIAppState {
-        private final String mIAppServiceId;
-        private final ComponentName mComponentName;
-
-        TvIAppState(String id, ComponentName componentName) {
-            mIAppServiceId = id;
-            mComponentName = componentName;
-        }
+        private String mIAppServiceId;
+        private ComponentName mComponentName;
+        private TvIAppInfo mInfo;
+        private int mUid;
+        private int mIAppNumber;
     }
 
     private final class SessionState implements IBinder.DeathRecipient {
@@ -649,9 +1140,11 @@
 
     private final class SessionCallback extends ITvIAppSessionCallback.Stub {
         private final SessionState mSessionState;
+        private final InputChannel[] mInputChannels;
 
-        SessionCallback(SessionState sessionState) {
+        SessionCallback(SessionState sessionState, InputChannel[] channels) {
             mSessionState = sessionState;
+            mInputChannels = channels;
         }
 
         @Override
@@ -667,12 +1160,14 @@
                             mSessionState.mClient,
                             mSessionState.mIAppServiceId,
                             mSessionState.mSessionToken,
+                            mInputChannels[0],
                             mSessionState.mSeq);
                 } else {
                     removeSessionStateLocked(mSessionState.mSessionToken, mSessionState.mUserId);
                     sendSessionTokenToClientLocked(mSessionState.mClient,
-                            mSessionState.mIAppServiceId, null, mSessionState.mSeq);
+                            mSessionState.mIAppServiceId, null, null, mSessionState.mSeq);
                 }
+                mInputChannels[0].dispose();
             }
         }
 
diff --git a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
index 1c46ac8..be13168 100644
--- a/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
+++ b/services/core/java/com/android/server/vcn/VcnGatewayConnection.java
@@ -87,9 +87,10 @@
 import com.android.internal.util.StateMachine;
 import com.android.internal.util.WakeupMessage;
 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
-import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
-import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback;
 import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
+import com.android.server.vcn.routeselection.UnderlyingNetworkController;
+import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback;
+import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
 import com.android.server.vcn.util.LogUtils;
 import com.android.server.vcn.util.MtuUtils;
 import com.android.server.vcn.util.OneWayBoolean;
@@ -201,7 +202,7 @@
     private interface EventInfo {}
 
     /**
-     * Sent when there are changes to the underlying network (per the UnderlyingNetworkTracker).
+     * Sent when there are changes to the underlying network (per the UnderlyingNetworkController).
      *
      * <p>May indicate an entirely new underlying network, OR a change in network properties.
      *
@@ -522,11 +523,14 @@
 
     @NonNull private final VcnContext mVcnContext;
     @NonNull private final ParcelUuid mSubscriptionGroup;
-    @NonNull private final UnderlyingNetworkTracker mUnderlyingNetworkTracker;
+    @NonNull private final UnderlyingNetworkController mUnderlyingNetworkController;
     @NonNull private final VcnGatewayConnectionConfig mConnectionConfig;
     @NonNull private final VcnGatewayStatusCallback mGatewayStatusCallback;
     @NonNull private final Dependencies mDeps;
-    @NonNull private final VcnUnderlyingNetworkTrackerCallback mUnderlyingNetworkTrackerCallback;
+
+    @NonNull
+    private final VcnUnderlyingNetworkControllerCallback mUnderlyingNetworkControllerCallback;
+
     private final boolean mIsMobileDataEnabled;
 
     @NonNull private final IpSecManager mIpSecManager;
@@ -674,17 +678,17 @@
 
         mLastSnapshot = Objects.requireNonNull(snapshot, "Missing snapshot");
 
-        mUnderlyingNetworkTrackerCallback = new VcnUnderlyingNetworkTrackerCallback();
+        mUnderlyingNetworkControllerCallback = new VcnUnderlyingNetworkControllerCallback();
 
         mWakeLock =
                 mDeps.newWakeLock(mVcnContext.getContext(), PowerManager.PARTIAL_WAKE_LOCK, TAG);
 
-        mUnderlyingNetworkTracker =
-                mDeps.newUnderlyingNetworkTracker(
+        mUnderlyingNetworkController =
+                mDeps.newUnderlyingNetworkController(
                         mVcnContext,
                         subscriptionGroup,
                         mLastSnapshot,
-                        mUnderlyingNetworkTrackerCallback);
+                        mUnderlyingNetworkControllerCallback);
         mIpSecManager = mVcnContext.getContext().getSystemService(IpSecManager.class);
 
         addState(mDisconnectedState);
@@ -748,7 +752,7 @@
         cancelRetryTimeoutAlarm();
         cancelSafeModeAlarm();
 
-        mUnderlyingNetworkTracker.teardown();
+        mUnderlyingNetworkController.teardown();
 
         mGatewayStatusCallback.onQuit();
     }
@@ -764,12 +768,13 @@
         mVcnContext.ensureRunningOnLooperThread();
 
         mLastSnapshot = snapshot;
-        mUnderlyingNetworkTracker.updateSubscriptionSnapshot(mLastSnapshot);
+        mUnderlyingNetworkController.updateSubscriptionSnapshot(mLastSnapshot);
 
         sendMessageAndAcquireWakeLock(EVENT_SUBSCRIPTIONS_CHANGED, TOKEN_ALL);
     }
 
-    private class VcnUnderlyingNetworkTrackerCallback implements UnderlyingNetworkTrackerCallback {
+    private class VcnUnderlyingNetworkControllerCallback
+            implements UnderlyingNetworkControllerCallback {
         @Override
         public void onSelectedUnderlyingNetworkChanged(
                 @Nullable UnderlyingNetworkRecord underlying) {
@@ -2264,7 +2269,7 @@
                         + (mNetworkAgent == null ? null : mNetworkAgent.getNetwork()));
         pw.println();
 
-        mUnderlyingNetworkTracker.dump(pw);
+        mUnderlyingNetworkController.dump(pw);
         pw.println();
 
         pw.decreaseIndent();
@@ -2276,8 +2281,8 @@
     }
 
     @VisibleForTesting(visibility = Visibility.PRIVATE)
-    UnderlyingNetworkTrackerCallback getUnderlyingNetworkTrackerCallback() {
-        return mUnderlyingNetworkTrackerCallback;
+    UnderlyingNetworkControllerCallback getUnderlyingNetworkControllerCallback() {
+        return mUnderlyingNetworkControllerCallback;
     }
 
     @VisibleForTesting(visibility = Visibility.PRIVATE)
@@ -2356,17 +2361,14 @@
     /** External dependencies used by VcnGatewayConnection, for injection in tests */
     @VisibleForTesting(visibility = Visibility.PRIVATE)
     public static class Dependencies {
-        /** Builds a new UnderlyingNetworkTracker. */
-        public UnderlyingNetworkTracker newUnderlyingNetworkTracker(
+        /** Builds a new UnderlyingNetworkController. */
+        public UnderlyingNetworkController newUnderlyingNetworkController(
                 VcnContext vcnContext,
                 ParcelUuid subscriptionGroup,
                 TelephonySubscriptionSnapshot snapshot,
-                UnderlyingNetworkTrackerCallback callback) {
-            return new UnderlyingNetworkTracker(
-                    vcnContext,
-                    subscriptionGroup,
-                    snapshot,
-                    callback);
+                UnderlyingNetworkControllerCallback callback) {
+            return new UnderlyingNetworkController(
+                    vcnContext, subscriptionGroup, snapshot, callback);
         }
 
         /** Builds a new IkeSession. */
diff --git a/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
new file mode 100644
index 0000000..bea8ae9
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/routeselection/NetworkPriorityClassifier.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2021 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.vcn.routeselection;
+
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+
+import static com.android.server.VcnManagementService.LOCAL_LOG;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.NetworkCapabilities;
+import android.net.vcn.VcnManager;
+import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+import android.telephony.SubscriptionManager;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
+
+import java.util.Set;
+
+/** @hide */
+class NetworkPriorityClassifier {
+    @NonNull private static final String TAG = NetworkPriorityClassifier.class.getSimpleName();
+    /**
+     * Minimum signal strength for a WiFi network to be eligible for switching to
+     *
+     * <p>A network that satisfies this is eligible to become the selected underlying network with
+     * no additional conditions
+     */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final int WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT = -70;
+    /**
+     * Minimum signal strength to continue using a WiFi network
+     *
+     * <p>A network that satisfies the conditions may ONLY continue to be used if it is already
+     * selected as the underlying network. A WiFi network satisfying this condition, but NOT the
+     * prospective-network RSSI threshold CANNOT be switched to.
+     */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final int WIFI_EXIT_RSSI_THRESHOLD_DEFAULT = -74;
+    /** Priority for any cellular network for which the subscription is listed as opportunistic */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final int PRIORITY_OPPORTUNISTIC_CELLULAR = 0;
+    /** Priority for any WiFi network which is in use, and satisfies the in-use RSSI threshold */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final int PRIORITY_WIFI_IN_USE = 1;
+    /** Priority for any WiFi network which satisfies the prospective-network RSSI threshold */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final int PRIORITY_WIFI_PROSPECTIVE = 2;
+    /** Priority for any standard macro cellular network */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final int PRIORITY_MACRO_CELLULAR = 3;
+    /** Priority for any other networks (including unvalidated, etc) */
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    static final int PRIORITY_ANY = Integer.MAX_VALUE;
+
+    private static final SparseArray<String> PRIORITY_TO_STRING_MAP = new SparseArray<>();
+
+    static {
+        PRIORITY_TO_STRING_MAP.put(
+                PRIORITY_OPPORTUNISTIC_CELLULAR, "PRIORITY_OPPORTUNISTIC_CELLULAR");
+        PRIORITY_TO_STRING_MAP.put(PRIORITY_WIFI_IN_USE, "PRIORITY_WIFI_IN_USE");
+        PRIORITY_TO_STRING_MAP.put(PRIORITY_WIFI_PROSPECTIVE, "PRIORITY_WIFI_PROSPECTIVE");
+        PRIORITY_TO_STRING_MAP.put(PRIORITY_MACRO_CELLULAR, "PRIORITY_MACRO_CELLULAR");
+        PRIORITY_TO_STRING_MAP.put(PRIORITY_ANY, "PRIORITY_ANY");
+    }
+
+    /**
+     * Gives networks a priority class, based on the following priorities:
+     *
+     * <ol>
+     *   <li>Opportunistic cellular
+     *   <li>Carrier WiFi, signal strength >= WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT
+     *   <li>Carrier WiFi, active network + signal strength >= WIFI_EXIT_RSSI_THRESHOLD_DEFAULT
+     *   <li>Macro cellular
+     *   <li>Any others
+     * </ol>
+     */
+    static int calculatePriorityClass(
+            UnderlyingNetworkRecord networkRecord,
+            ParcelUuid subscriptionGroup,
+            TelephonySubscriptionSnapshot snapshot,
+            UnderlyingNetworkRecord currentlySelected,
+            PersistableBundle carrierConfig) {
+        final NetworkCapabilities caps = networkRecord.networkCapabilities;
+
+        // mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED
+
+        if (networkRecord.isBlocked) {
+            logWtf("Network blocked for System Server: " + networkRecord.network);
+            return PRIORITY_ANY;
+        }
+
+        if (caps.hasTransport(TRANSPORT_CELLULAR)
+                && isOpportunistic(snapshot, caps.getSubscriptionIds())) {
+            // If this carrier is the active data provider, ensure that opportunistic is only
+            // ever prioritized if it is also the active data subscription. This ensures that
+            // if an opportunistic subscription is still in the process of being switched to,
+            // or switched away from, the VCN does not attempt to continue using it against the
+            // decision made at the telephony layer. Failure to do so may result in the modem
+            // switching back and forth.
+            //
+            // Allow the following two cases:
+            // 1. Active subId is NOT in the group that this VCN is supporting
+            // 2. This opportunistic subscription is for the active subId
+            if (!snapshot.getAllSubIdsInGroup(subscriptionGroup)
+                            .contains(SubscriptionManager.getActiveDataSubscriptionId())
+                    || caps.getSubscriptionIds()
+                            .contains(SubscriptionManager.getActiveDataSubscriptionId())) {
+                return PRIORITY_OPPORTUNISTIC_CELLULAR;
+            }
+        }
+
+        if (caps.hasTransport(TRANSPORT_WIFI)) {
+            if (caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)
+                    && currentlySelected != null
+                    && networkRecord.network.equals(currentlySelected.network)) {
+                return PRIORITY_WIFI_IN_USE;
+            }
+
+            if (caps.getSignalStrength() >= getWifiEntryRssiThreshold(carrierConfig)) {
+                return PRIORITY_WIFI_PROSPECTIVE;
+            }
+        }
+
+        // Disallow opportunistic subscriptions from matching PRIORITY_MACRO_CELLULAR, as might
+        // be the case when Default Data SubId (CBRS) != Active Data SubId (MACRO), as might be
+        // the case if the Default Data SubId does not support certain services (eg voice
+        // calling)
+        if (caps.hasTransport(TRANSPORT_CELLULAR)
+                && !isOpportunistic(snapshot, caps.getSubscriptionIds())) {
+            return PRIORITY_MACRO_CELLULAR;
+        }
+
+        return PRIORITY_ANY;
+    }
+
+    static boolean isOpportunistic(
+            @NonNull TelephonySubscriptionSnapshot snapshot, Set<Integer> subIds) {
+        if (snapshot == null) {
+            logWtf("Got null snapshot");
+            return false;
+        }
+        for (int subId : subIds) {
+            if (snapshot.isOpportunistic(subId)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static int getWifiEntryRssiThreshold(@Nullable PersistableBundle carrierConfig) {
+        if (carrierConfig != null) {
+            return carrierConfig.getInt(
+                    VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY,
+                    WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT);
+        }
+        return WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT;
+    }
+
+    static int getWifiExitRssiThreshold(@Nullable PersistableBundle carrierConfig) {
+        if (carrierConfig != null) {
+            return carrierConfig.getInt(
+                    VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
+                    WIFI_EXIT_RSSI_THRESHOLD_DEFAULT);
+        }
+        return WIFI_EXIT_RSSI_THRESHOLD_DEFAULT;
+    }
+
+    static String priorityClassToString(int priorityClass) {
+        return PRIORITY_TO_STRING_MAP.get(priorityClass, "unknown");
+    }
+
+    private static void logWtf(String msg) {
+        Slog.wtf(TAG, msg);
+        LOCAL_LOG.log(TAG + " WTF: " + msg);
+    }
+}
diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
similarity index 60%
rename from services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
rename to services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
index 7ddd135..071c7a6 100644
--- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkController.java
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package com.android.server.vcn;
+package com.android.server.vcn.routeselection;
 
-import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
-import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
 import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
 
 import static com.android.server.VcnManagementService.LOCAL_LOG;
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.getWifiEntryRssiThreshold;
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.getWifiExitRssiThreshold;
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.isOpportunistic;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -31,27 +32,23 @@
 import android.net.NetworkCapabilities;
 import android.net.NetworkRequest;
 import android.net.TelephonyNetworkSpecifier;
-import android.net.vcn.VcnManager;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.ParcelUuid;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
-import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyCallback;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 import android.util.Slog;
-import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.annotations.VisibleForTesting.Visibility;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
+import com.android.server.vcn.VcnContext;
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -61,68 +58,18 @@
 /**
  * Tracks a set of Networks underpinning a VcnGatewayConnection.
  *
- * <p>A single UnderlyingNetworkTracker is built to serve a SINGLE VCN Gateway Connection, and MUST
- * be torn down with the VcnGatewayConnection in order to ensure underlying networks are allowed to
- * be reaped.
+ * <p>A single UnderlyingNetworkController is built to serve a SINGLE VCN Gateway Connection, and
+ * MUST be torn down with the VcnGatewayConnection in order to ensure underlying networks are
+ * allowed to be reaped.
  *
  * @hide
  */
-public class UnderlyingNetworkTracker {
-    @NonNull private static final String TAG = UnderlyingNetworkTracker.class.getSimpleName();
-
-    /**
-     * Minimum signal strength for a WiFi network to be eligible for switching to
-     *
-     * <p>A network that satisfies this is eligible to become the selected underlying network with
-     * no additional conditions
-     */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT = -70;
-
-    /**
-     * Minimum signal strength to continue using a WiFi network
-     *
-     * <p>A network that satisfies the conditions may ONLY continue to be used if it is already
-     * selected as the underlying network. A WiFi network satisfying this condition, but NOT the
-     * prospective-network RSSI threshold CANNOT be switched to.
-     */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int WIFI_EXIT_RSSI_THRESHOLD_DEFAULT = -74;
-
-    /** Priority for any cellular network for which the subscription is listed as opportunistic */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int PRIORITY_OPPORTUNISTIC_CELLULAR = 0;
-
-    /** Priority for any WiFi network which is in use, and satisfies the in-use RSSI threshold */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int PRIORITY_WIFI_IN_USE = 1;
-
-    /** Priority for any WiFi network which satisfies the prospective-network RSSI threshold */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int PRIORITY_WIFI_PROSPECTIVE = 2;
-
-    /** Priority for any standard macro cellular network */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int PRIORITY_MACRO_CELLULAR = 3;
-
-    /** Priority for any other networks (including unvalidated, etc) */
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    static final int PRIORITY_ANY = Integer.MAX_VALUE;
-
-    private static final SparseArray<String> PRIORITY_TO_STRING_MAP = new SparseArray<>();
-
-    static {
-        PRIORITY_TO_STRING_MAP.put(
-                PRIORITY_OPPORTUNISTIC_CELLULAR, "PRIORITY_OPPORTUNISTIC_CELLULAR");
-        PRIORITY_TO_STRING_MAP.put(PRIORITY_WIFI_IN_USE, "PRIORITY_WIFI_IN_USE");
-        PRIORITY_TO_STRING_MAP.put(PRIORITY_WIFI_PROSPECTIVE, "PRIORITY_WIFI_PROSPECTIVE");
-        PRIORITY_TO_STRING_MAP.put(PRIORITY_MACRO_CELLULAR, "PRIORITY_MACRO_CELLULAR");
-        PRIORITY_TO_STRING_MAP.put(PRIORITY_ANY, "PRIORITY_ANY");
-    }
+public class UnderlyingNetworkController {
+    @NonNull private static final String TAG = UnderlyingNetworkController.class.getSimpleName();
 
     @NonNull private final VcnContext mVcnContext;
     @NonNull private final ParcelUuid mSubscriptionGroup;
-    @NonNull private final UnderlyingNetworkTrackerCallback mCb;
+    @NonNull private final UnderlyingNetworkControllerCallback mCb;
     @NonNull private final Dependencies mDeps;
     @NonNull private final Handler mHandler;
     @NonNull private final ConnectivityManager mConnectivityManager;
@@ -142,11 +89,11 @@
     @Nullable private UnderlyingNetworkRecord mCurrentRecord;
     @Nullable private UnderlyingNetworkRecord.Builder mRecordInProgress;
 
-    public UnderlyingNetworkTracker(
+    public UnderlyingNetworkController(
             @NonNull VcnContext vcnContext,
             @NonNull ParcelUuid subscriptionGroup,
             @NonNull TelephonySubscriptionSnapshot snapshot,
-            @NonNull UnderlyingNetworkTrackerCallback cb) {
+            @NonNull UnderlyingNetworkControllerCallback cb) {
         this(
                 vcnContext,
                 subscriptionGroup,
@@ -155,11 +102,11 @@
                 new Dependencies());
     }
 
-    private UnderlyingNetworkTracker(
+    private UnderlyingNetworkController(
             @NonNull VcnContext vcnContext,
             @NonNull ParcelUuid subscriptionGroup,
             @NonNull TelephonySubscriptionSnapshot snapshot,
-            @NonNull UnderlyingNetworkTrackerCallback cb,
+            @NonNull UnderlyingNetworkControllerCallback cb,
             @NonNull Dependencies deps) {
         mVcnContext = Objects.requireNonNull(vcnContext, "Missing vcnContext");
         mSubscriptionGroup = Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
@@ -271,8 +218,8 @@
      * subscription group, while the VCN networks are excluded by virtue of not having subIds set on
      * the VCN-exposed networks.
      *
-     * <p>If the VCN that this UnderlyingNetworkTracker belongs to is in test-mode, this will return
-     * a NetworkRequest that only matches Test Networks.
+     * <p>If the VCN that this UnderlyingNetworkController belongs to is in test-mode, this will
+     * return a NetworkRequest that only matches Test Networks.
      */
     private NetworkRequest getRouteSelectionRequest() {
         if (mVcnContext.isInTestMode()) {
@@ -373,9 +320,9 @@
     }
 
     /**
-     * Update this UnderlyingNetworkTracker's TelephonySubscriptionSnapshot.
+     * Update this UnderlyingNetworkController's TelephonySubscriptionSnapshot.
      *
-     * <p>Updating the TelephonySubscriptionSnapshot will cause this UnderlyingNetworkTracker to
+     * <p>Updating the TelephonySubscriptionSnapshot will cause this UnderlyingNetworkController to
      * reevaluate its NetworkBringupCallbacks. This may result in NetworkRequests being registered
      * or unregistered if the subIds mapped to the this Tracker's SubscriptionGroup change.
      */
@@ -410,7 +357,7 @@
 
     private void reevaluateNetworks() {
         if (mIsQuitting || mRouteSelectionCallback == null) {
-            return; // UnderlyingNetworkTracker has quit.
+            return; // UnderlyingNetworkController has quit.
         }
 
         TreeSet<UnderlyingNetworkRecord> sorted =
@@ -424,22 +371,6 @@
         mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord);
     }
 
-    private static boolean isOpportunistic(
-            @NonNull TelephonySubscriptionSnapshot snapshot, Set<Integer> subIds) {
-        if (snapshot == null) {
-            logWtf("Got null snapshot");
-            return false;
-        }
-
-        for (int subId : subIds) {
-            if (snapshot.isOpportunistic(subId)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
     /**
      * NetworkBringupCallback is used to keep background, VCN-managed Networks from being reaped.
      *
@@ -544,230 +475,6 @@
         }
     }
 
-    private static int getWifiEntryRssiThreshold(@Nullable PersistableBundle carrierConfig) {
-        if (carrierConfig != null) {
-            return carrierConfig.getInt(
-                    VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY,
-                    WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT);
-        }
-
-        return WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT;
-    }
-
-    private static int getWifiExitRssiThreshold(@Nullable PersistableBundle carrierConfig) {
-        if (carrierConfig != null) {
-            return carrierConfig.getInt(
-                    VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
-                    WIFI_EXIT_RSSI_THRESHOLD_DEFAULT);
-        }
-
-        return WIFI_EXIT_RSSI_THRESHOLD_DEFAULT;
-    }
-
-    /** A record of a single underlying network, caching relevant fields. */
-    public static class UnderlyingNetworkRecord {
-        @NonNull public final Network network;
-        @NonNull public final NetworkCapabilities networkCapabilities;
-        @NonNull public final LinkProperties linkProperties;
-        public final boolean isBlocked;
-
-        @VisibleForTesting(visibility = Visibility.PRIVATE)
-        UnderlyingNetworkRecord(
-                @NonNull Network network,
-                @NonNull NetworkCapabilities networkCapabilities,
-                @NonNull LinkProperties linkProperties,
-                boolean isBlocked) {
-            this.network = network;
-            this.networkCapabilities = networkCapabilities;
-            this.linkProperties = linkProperties;
-            this.isBlocked = isBlocked;
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            if (this == o) return true;
-            if (!(o instanceof UnderlyingNetworkRecord)) return false;
-            final UnderlyingNetworkRecord that = (UnderlyingNetworkRecord) o;
-
-            return network.equals(that.network)
-                    && networkCapabilities.equals(that.networkCapabilities)
-                    && linkProperties.equals(that.linkProperties)
-                    && isBlocked == that.isBlocked;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(network, networkCapabilities, linkProperties, isBlocked);
-        }
-
-        /**
-         * Gives networks a priority class, based on the following priorities:
-         *
-         * <ol>
-         *   <li>Opportunistic cellular
-         *   <li>Carrier WiFi, signal strength >= WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT
-         *   <li>Carrier WiFi, active network + signal strength >= WIFI_EXIT_RSSI_THRESHOLD_DEFAULT
-         *   <li>Macro cellular
-         *   <li>Any others
-         * </ol>
-         */
-        private int calculatePriorityClass(
-                ParcelUuid subscriptionGroup,
-                TelephonySubscriptionSnapshot snapshot,
-                UnderlyingNetworkRecord currentlySelected,
-                PersistableBundle carrierConfig) {
-            final NetworkCapabilities caps = networkCapabilities;
-
-            // mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED
-
-            if (isBlocked) {
-                logWtf("Network blocked for System Server: " + network);
-                return PRIORITY_ANY;
-            }
-
-            if (caps.hasTransport(TRANSPORT_CELLULAR)
-                    && isOpportunistic(snapshot, caps.getSubscriptionIds())) {
-                // If this carrier is the active data provider, ensure that opportunistic is only
-                // ever prioritized if it is also the active data subscription. This ensures that
-                // if an opportunistic subscription is still in the process of being switched to,
-                // or switched away from, the VCN does not attempt to continue using it against the
-                // decision made at the telephony layer. Failure to do so may result in the modem
-                // switching back and forth.
-                //
-                // Allow the following two cases:
-                // 1. Active subId is NOT in the group that this VCN is supporting
-                // 2. This opportunistic subscription is for the active subId
-                if (!snapshot.getAllSubIdsInGroup(subscriptionGroup)
-                                .contains(SubscriptionManager.getActiveDataSubscriptionId())
-                        || caps.getSubscriptionIds()
-                                .contains(SubscriptionManager.getActiveDataSubscriptionId())) {
-                    return PRIORITY_OPPORTUNISTIC_CELLULAR;
-                }
-            }
-
-            if (caps.hasTransport(TRANSPORT_WIFI)) {
-                if (caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)
-                        && currentlySelected != null
-                        && network.equals(currentlySelected.network)) {
-                    return PRIORITY_WIFI_IN_USE;
-                }
-
-                if (caps.getSignalStrength() >= getWifiEntryRssiThreshold(carrierConfig)) {
-                    return PRIORITY_WIFI_PROSPECTIVE;
-                }
-            }
-
-            // Disallow opportunistic subscriptions from matching PRIORITY_MACRO_CELLULAR, as might
-            // be the case when Default Data SubId (CBRS) != Active Data SubId (MACRO), as might be
-            // the case if the Default Data SubId does not support certain services (eg voice
-            // calling)
-            if (caps.hasTransport(TRANSPORT_CELLULAR)
-                    && !isOpportunistic(snapshot, caps.getSubscriptionIds())) {
-                return PRIORITY_MACRO_CELLULAR;
-            }
-
-            return PRIORITY_ANY;
-        }
-
-        private static Comparator<UnderlyingNetworkRecord> getComparator(
-                ParcelUuid subscriptionGroup,
-                TelephonySubscriptionSnapshot snapshot,
-                UnderlyingNetworkRecord currentlySelected,
-                PersistableBundle carrierConfig) {
-            return (left, right) -> {
-                return Integer.compare(
-                        left.calculatePriorityClass(
-                                subscriptionGroup, snapshot, currentlySelected, carrierConfig),
-                        right.calculatePriorityClass(
-                                subscriptionGroup, snapshot, currentlySelected, carrierConfig));
-            };
-        }
-
-        /** Dumps the state of this record for logging and debugging purposes. */
-        private void dump(
-                IndentingPrintWriter pw,
-                ParcelUuid subscriptionGroup,
-                TelephonySubscriptionSnapshot snapshot,
-                UnderlyingNetworkRecord currentlySelected,
-                PersistableBundle carrierConfig) {
-            pw.println("UnderlyingNetworkRecord:");
-            pw.increaseIndent();
-
-            final int priorityClass =
-                    calculatePriorityClass(
-                            subscriptionGroup, snapshot, currentlySelected, carrierConfig);
-            pw.println(
-                    "Priority class: " + PRIORITY_TO_STRING_MAP.get(priorityClass) + " ("
-                            + priorityClass + ")");
-            pw.println("mNetwork: " + network);
-            pw.println("mNetworkCapabilities: " + networkCapabilities);
-            pw.println("mLinkProperties: " + linkProperties);
-
-            pw.decreaseIndent();
-        }
-
-        /** Builder to incrementally construct an UnderlyingNetworkRecord. */
-        private static class Builder {
-            @NonNull private final Network mNetwork;
-
-            @Nullable private NetworkCapabilities mNetworkCapabilities;
-            @Nullable private LinkProperties mLinkProperties;
-            boolean mIsBlocked;
-            boolean mWasIsBlockedSet;
-
-            @Nullable private UnderlyingNetworkRecord mCached;
-
-            private Builder(@NonNull Network network) {
-                mNetwork = network;
-            }
-
-            @NonNull
-            private Network getNetwork() {
-                return mNetwork;
-            }
-
-            private void setNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
-                mNetworkCapabilities = networkCapabilities;
-                mCached = null;
-            }
-
-            @Nullable
-            private NetworkCapabilities getNetworkCapabilities() {
-                return mNetworkCapabilities;
-            }
-
-            private void setLinkProperties(@NonNull LinkProperties linkProperties) {
-                mLinkProperties = linkProperties;
-                mCached = null;
-            }
-
-            private void setIsBlocked(boolean isBlocked) {
-                mIsBlocked = isBlocked;
-                mWasIsBlockedSet = true;
-                mCached = null;
-            }
-
-            private boolean isValid() {
-                return mNetworkCapabilities != null && mLinkProperties != null && mWasIsBlockedSet;
-            }
-
-            private UnderlyingNetworkRecord build() {
-                if (!isValid()) {
-                    throw new IllegalArgumentException(
-                            "Called build before UnderlyingNetworkRecord was valid");
-                }
-
-                if (mCached == null) {
-                    mCached =
-                            new UnderlyingNetworkRecord(
-                                    mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked);
-                }
-
-                return mCached;
-            }
-        }
-    }
-
     private static void logWtf(String msg) {
         Slog.wtf(TAG, msg);
         LOCAL_LOG.log(TAG + " WTF: " + msg);
@@ -780,7 +487,7 @@
 
     /** Dumps the state of this record for logging and debugging purposes. */
     public void dump(IndentingPrintWriter pw) {
-        pw.println("UnderlyingNetworkTracker:");
+        pw.println("UnderlyingNetworkController:");
         pw.increaseIndent();
 
         pw.println("Carrier WiFi Entry Threshold: " + getWifiEntryRssiThreshold(mCarrierConfig));
@@ -811,7 +518,7 @@
     }
 
     /** Callbacks for being notified of the changes in, or to the selected underlying network. */
-    public interface UnderlyingNetworkTrackerCallback {
+    public interface UnderlyingNetworkControllerCallback {
         /**
          * Fired when a new underlying network is selected, or properties have changed.
          *
diff --git a/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
new file mode 100644
index 0000000..65c69de
--- /dev/null
+++ b/services/core/java/com/android/server/vcn/routeselection/UnderlyingNetworkRecord.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2021 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.vcn.routeselection;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.LinkProperties;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.annotations.VisibleForTesting.Visibility;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
+
+import java.util.Comparator;
+import java.util.Objects;
+
+/**
+ * A record of a single underlying network, caching relevant fields.
+ *
+ * @hide
+ */
+public class UnderlyingNetworkRecord {
+    @NonNull public final Network network;
+    @NonNull public final NetworkCapabilities networkCapabilities;
+    @NonNull public final LinkProperties linkProperties;
+    public final boolean isBlocked;
+
+    @VisibleForTesting(visibility = Visibility.PRIVATE)
+    public UnderlyingNetworkRecord(
+            @NonNull Network network,
+            @NonNull NetworkCapabilities networkCapabilities,
+            @NonNull LinkProperties linkProperties,
+            boolean isBlocked) {
+        this.network = network;
+        this.networkCapabilities = networkCapabilities;
+        this.linkProperties = linkProperties;
+        this.isBlocked = isBlocked;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof UnderlyingNetworkRecord)) return false;
+        final UnderlyingNetworkRecord that = (UnderlyingNetworkRecord) o;
+
+        return network.equals(that.network)
+                && networkCapabilities.equals(that.networkCapabilities)
+                && linkProperties.equals(that.linkProperties)
+                && isBlocked == that.isBlocked;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(network, networkCapabilities, linkProperties, isBlocked);
+    }
+
+    static Comparator<UnderlyingNetworkRecord> getComparator(
+            ParcelUuid subscriptionGroup,
+            TelephonySubscriptionSnapshot snapshot,
+            UnderlyingNetworkRecord currentlySelected,
+            PersistableBundle carrierConfig) {
+        return (left, right) -> {
+            return Integer.compare(
+                    NetworkPriorityClassifier.calculatePriorityClass(
+                            left, subscriptionGroup, snapshot, currentlySelected, carrierConfig),
+                    NetworkPriorityClassifier.calculatePriorityClass(
+                            right, subscriptionGroup, snapshot, currentlySelected, carrierConfig));
+        };
+    }
+
+    /** Dumps the state of this record for logging and debugging purposes. */
+    void dump(
+            IndentingPrintWriter pw,
+            ParcelUuid subscriptionGroup,
+            TelephonySubscriptionSnapshot snapshot,
+            UnderlyingNetworkRecord currentlySelected,
+            PersistableBundle carrierConfig) {
+        pw.println("UnderlyingNetworkRecord:");
+        pw.increaseIndent();
+
+        final int priorityClass =
+                NetworkPriorityClassifier.calculatePriorityClass(
+                        this, subscriptionGroup, snapshot, currentlySelected, carrierConfig);
+        pw.println(
+                "Priority class: "
+                        + NetworkPriorityClassifier.priorityClassToString(priorityClass)
+                        + " ("
+                        + priorityClass
+                        + ")");
+        pw.println("mNetwork: " + network);
+        pw.println("mNetworkCapabilities: " + networkCapabilities);
+        pw.println("mLinkProperties: " + linkProperties);
+
+        pw.decreaseIndent();
+    }
+
+    /** Builder to incrementally construct an UnderlyingNetworkRecord. */
+    static class Builder {
+        @NonNull private final Network mNetwork;
+
+        @Nullable private NetworkCapabilities mNetworkCapabilities;
+        @Nullable private LinkProperties mLinkProperties;
+        boolean mIsBlocked;
+        boolean mWasIsBlockedSet;
+
+        @Nullable private UnderlyingNetworkRecord mCached;
+
+        Builder(@NonNull Network network) {
+            mNetwork = network;
+        }
+
+        @NonNull
+        Network getNetwork() {
+            return mNetwork;
+        }
+
+        void setNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
+            mNetworkCapabilities = networkCapabilities;
+            mCached = null;
+        }
+
+        @Nullable
+        NetworkCapabilities getNetworkCapabilities() {
+            return mNetworkCapabilities;
+        }
+
+        void setLinkProperties(@NonNull LinkProperties linkProperties) {
+            mLinkProperties = linkProperties;
+            mCached = null;
+        }
+
+        void setIsBlocked(boolean isBlocked) {
+            mIsBlocked = isBlocked;
+            mWasIsBlockedSet = true;
+            mCached = null;
+        }
+
+        boolean isValid() {
+            return mNetworkCapabilities != null && mLinkProperties != null && mWasIsBlockedSet;
+        }
+
+        UnderlyingNetworkRecord build() {
+            if (!isValid()) {
+                throw new IllegalArgumentException(
+                        "Called build before UnderlyingNetworkRecord was valid");
+            }
+
+            if (mCached == null) {
+                mCached =
+                        new UnderlyingNetworkRecord(
+                                mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked);
+            }
+
+            return mCached;
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/vibrator/VibrationSettings.java b/services/core/java/com/android/server/vibrator/VibrationSettings.java
index 95305ba..f82f99d 100644
--- a/services/core/java/com/android/server/vibrator/VibrationSettings.java
+++ b/services/core/java/com/android/server/vibrator/VibrationSettings.java
@@ -16,6 +16,14 @@
 
 package com.android.server.vibrator;
 
+import static android.os.VibrationAttributes.USAGE_ALARM;
+import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
+import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK;
+import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
+import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION;
+import static android.os.VibrationAttributes.USAGE_RINGTONE;
+import static android.os.VibrationAttributes.USAGE_TOUCH;
+
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.IUidObserver;
@@ -90,6 +98,8 @@
     @GuardedBy("mLock")
     private int mHapticFeedbackIntensity;
     @GuardedBy("mLock")
+    private int mHardwareFeedbackIntensity;
+    @GuardedBy("mLock")
     private int mNotificationIntensity;
     @GuardedBy("mLock")
     private int mRingIntensity;
@@ -171,10 +181,12 @@
                     }
                 });
 
-        mContext.registerReceiver(mUserReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
+        IntentFilter filter = new IntentFilter(Intent.ACTION_USER_SWITCHED);
+        mContext.registerReceiver(mUserReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
+
         registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES));
         registerSettingsObserver(Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING));
-        registerSettingsObserver(Settings.Global.getUriFor(Settings.Global.APPLY_RAMPING_RINGER));
+        registerSettingsObserver(Settings.System.getUriFor(Settings.System.APPLY_RAMPING_RINGER));
         registerSettingsObserver(Settings.Global.getUriFor(Settings.Global.ZEN_MODE));
         registerSettingsObserver(
                 Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_INTENSITY));
@@ -230,17 +242,20 @@
      * @return The vibration intensity, one of Vibrator.VIBRATION_INTENSITY_*
      */
     public int getDefaultIntensity(int usageHint) {
-        if (isAlarm(usageHint)) {
+        if (usageHint == USAGE_ALARM) {
             return Vibrator.VIBRATION_INTENSITY_HIGH;
         }
         synchronized (mLock) {
             if (mVibrator != null) {
-                if (isRingtone(usageHint)) {
-                    return mVibrator.getDefaultRingVibrationIntensity();
-                } else if (isNotification(usageHint)) {
-                    return mVibrator.getDefaultNotificationVibrationIntensity();
-                } else if (isHapticFeedback(usageHint)) {
-                    return mVibrator.getDefaultHapticFeedbackIntensity();
+                switch (usageHint) {
+                    case USAGE_RINGTONE:
+                        return mVibrator.getDefaultRingVibrationIntensity();
+                    case USAGE_NOTIFICATION:
+                        return mVibrator.getDefaultNotificationVibrationIntensity();
+                    case USAGE_TOUCH:
+                    case USAGE_HARDWARE_FEEDBACK:
+                    case USAGE_PHYSICAL_EMULATION:
+                        return mVibrator.getDefaultHapticFeedbackIntensity();
                 }
             }
         }
@@ -255,16 +270,20 @@
      */
     public int getCurrentIntensity(int usageHint) {
         synchronized (mLock) {
-            if (isRingtone(usageHint)) {
-                return mRingIntensity;
-            } else if (isNotification(usageHint)) {
-                return mNotificationIntensity;
-            } else if (isHapticFeedback(usageHint)) {
-                return mHapticFeedbackIntensity;
-            } else if (isAlarm(usageHint)) {
-                return Vibrator.VIBRATION_INTENSITY_HIGH;
-            } else {
-                return Vibrator.VIBRATION_INTENSITY_MEDIUM;
+            switch (usageHint) {
+                case USAGE_RINGTONE:
+                    return mRingIntensity;
+                case USAGE_NOTIFICATION:
+                    return mNotificationIntensity;
+                case USAGE_TOUCH:
+                    return mHapticFeedbackIntensity;
+                case USAGE_HARDWARE_FEEDBACK:
+                case USAGE_PHYSICAL_EMULATION:
+                    return mHardwareFeedbackIntensity;
+                case USAGE_ALARM:
+                    return Vibrator.VIBRATION_INTENSITY_HIGH;
+                default:
+                    return Vibrator.VIBRATION_INTENSITY_MEDIUM;
             }
         }
     }
@@ -287,7 +306,7 @@
      * for ringtone usage only. All other usages are allowed independently of ringer mode.
      */
     public boolean shouldVibrateForRingerMode(int usageHint) {
-        if (!isRingtone(usageHint)) {
+        if (usageHint != USAGE_RINGTONE) {
             return true;
         }
         synchronized (mLock) {
@@ -322,8 +341,10 @@
      * {@link VibrationAttributes#USAGE_COMMUNICATION_REQUEST} usages are allowed to vibrate.
      */
     public boolean shouldVibrateForPowerMode(int usageHint) {
-        return !mLowPowerMode || isRingtone(usageHint) || isAlarm(usageHint)
-                || usageHint == VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
+        synchronized (mLock) {
+            return !mLowPowerMode || usageHint == USAGE_RINGTONE || usageHint == USAGE_ALARM
+                    || usageHint == USAGE_COMMUNICATION_REQUEST;
+        }
     }
 
     /** Return {@code true} if input devices should vibrate instead of this device. */
@@ -336,22 +357,6 @@
         return mZenMode != Settings.Global.ZEN_MODE_OFF;
     }
 
-    private static boolean isNotification(int usageHint) {
-        return usageHint == VibrationAttributes.USAGE_NOTIFICATION;
-    }
-
-    private static boolean isRingtone(int usageHint) {
-        return usageHint == VibrationAttributes.USAGE_RINGTONE;
-    }
-
-    private static boolean isHapticFeedback(int usageHint) {
-        return usageHint == VibrationAttributes.USAGE_TOUCH;
-    }
-
-    private static boolean isAlarm(int usageHint) {
-        return usageHint == VibrationAttributes.USAGE_ALARM;
-    }
-
     private static boolean isClassAlarm(int usageHint) {
         return (usageHint & VibrationAttributes.USAGE_CLASS_MASK)
                 == VibrationAttributes.USAGE_CLASS_ALARM;
@@ -361,20 +366,37 @@
     public void updateSettings() {
         synchronized (mLock) {
             mVibrateWhenRinging = getSystemSetting(Settings.System.VIBRATE_WHEN_RINGING, 0) != 0;
-            mApplyRampingRinger = getGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0) != 0;
+            mApplyRampingRinger = getSystemSetting(Settings.System.APPLY_RAMPING_RINGER, 0) != 0;
             mHapticFeedbackIntensity = getSystemSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
-                    getDefaultIntensity(VibrationAttributes.USAGE_TOUCH));
+                    getDefaultIntensity(USAGE_TOUCH));
+            mHardwareFeedbackIntensity = getSystemSetting(
+                    Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY,
+                    getHardwareFeedbackIntensityWhenSettingIsMissing(mHapticFeedbackIntensity));
             mNotificationIntensity = getSystemSetting(
                     Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
-                    getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION));
+                    getDefaultIntensity(USAGE_NOTIFICATION));
             mRingIntensity = getSystemSetting(Settings.System.RING_VIBRATION_INTENSITY,
-                    getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE));
+                    getDefaultIntensity(USAGE_RINGTONE));
             mVibrateInputDevices = getSystemSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0) > 0;
             mZenMode = getGlobalSetting(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
         }
         notifyListeners();
     }
 
+    /**
+     * Return the value to be used for {@link Settings.System#HARDWARE_HAPTIC_FEEDBACK_INTENSITY}
+     * when the value was not set by the user.
+     *
+     * <p>This should adapt the behavior preceding the introduction of this new setting key, which
+     * is to apply {@link Settings.System#HAPTIC_FEEDBACK_INTENSITY} unless it's disabled.
+     */
+    private int getHardwareFeedbackIntensityWhenSettingIsMissing(int hapticFeedbackIntensity) {
+        if (hapticFeedbackIntensity == Vibrator.VIBRATION_INTENSITY_OFF) {
+            return getDefaultIntensity(USAGE_HARDWARE_FEEDBACK);
+        }
+        return hapticFeedbackIntensity;
+    }
+
     @Override
     public String toString() {
         return "VibrationSettings{"
@@ -387,18 +409,20 @@
                 + ", mHapticChannelMaxVibrationAmplitude=" + getHapticChannelMaxVibrationAmplitude()
                 + ", mRampStepDuration=" + mRampStepDuration
                 + ", mRampDownDuration=" + mRampDownDuration
+                + ", mHardwareHapticFeedbackIntensity="
+                + intensityToString(getCurrentIntensity(USAGE_HARDWARE_FEEDBACK))
                 + ", mHapticFeedbackIntensity="
-                + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_TOUCH))
+                + intensityToString(getCurrentIntensity(USAGE_TOUCH))
                 + ", mHapticFeedbackDefaultIntensity="
-                + intensityToString(getDefaultIntensity(VibrationAttributes.USAGE_TOUCH))
+                + intensityToString(getDefaultIntensity(USAGE_TOUCH))
                 + ", mNotificationIntensity="
-                + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_NOTIFICATION))
+                + intensityToString(getCurrentIntensity(USAGE_NOTIFICATION))
                 + ", mNotificationDefaultIntensity="
-                + intensityToString(getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION))
+                + intensityToString(getDefaultIntensity(USAGE_NOTIFICATION))
                 + ", mRingIntensity="
-                + intensityToString(getCurrentIntensity(VibrationAttributes.USAGE_RINGTONE))
+                + intensityToString(getCurrentIntensity(USAGE_RINGTONE))
                 + ", mRingDefaultIntensity="
-                + intensityToString(getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE))
+                + intensityToString(getDefaultIntensity(USAGE_RINGTONE))
                 + '}';
     }
 
@@ -408,15 +432,15 @@
             proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_INTENSITY,
                     mHapticFeedbackIntensity);
             proto.write(VibratorManagerServiceDumpProto.HAPTIC_FEEDBACK_DEFAULT_INTENSITY,
-                    getDefaultIntensity(VibrationAttributes.USAGE_TOUCH));
+                    getDefaultIntensity(USAGE_TOUCH));
             proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_INTENSITY,
                     mNotificationIntensity);
             proto.write(VibratorManagerServiceDumpProto.NOTIFICATION_DEFAULT_INTENSITY,
-                    getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION));
+                    getDefaultIntensity(USAGE_NOTIFICATION));
             proto.write(VibratorManagerServiceDumpProto.RING_INTENSITY,
                     mRingIntensity);
             proto.write(VibratorManagerServiceDumpProto.RING_DEFAULT_INTENSITY,
-                    getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE));
+                    getDefaultIntensity(USAGE_RINGTONE));
         }
     }
 
diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java
index a327382..fdd9913 100644
--- a/services/core/java/com/android/server/vibrator/VibrationThread.java
+++ b/services/core/java/com/android/server/vibrator/VibrationThread.java
@@ -287,6 +287,9 @@
                 }
                 // If we waited, the queue may have changed, so let the loop run again.
                 if (waitTime <= 0) {
+                    if (DEBUG) {
+                        Slog.d(TAG, "Play vibration consuming next step...");
+                    }
                     mStepQueue.consumeNext();
                 }
                 Vibration.Status status = mStop ? Vibration.Status.CANCELLED
diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java
index 4b7fd90..4a1b95b 100644
--- a/services/core/java/com/android/server/vibrator/VibratorController.java
+++ b/services/core/java/com/android/server/vibrator/VibratorController.java
@@ -40,21 +40,22 @@
     private static final int SUGGESTED_FREQUENCY_SAFE_RANGE = 200;
 
     private final Object mLock = new Object();
-    private final NativeWrapper mNativeWrapper;
 
     @GuardedBy("mLock")
-    private VibratorInfo mVibratorInfo;
-    @GuardedBy("mLock")
-    private boolean mVibratorInfoLoadSuccessful;
-    @GuardedBy("mLock")
+    private final NativeWrapper mNativeWrapper;
+
+    // Vibrator state listeners that support concurrent updates and broadcasts, but should lock
+    // while broadcasting to guarantee delivery order.
     private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners =
             new RemoteCallbackList<>();
-    @GuardedBy("mLock")
-    private boolean mIsVibrating;
-    @GuardedBy("mLock")
-    private boolean mIsUnderExternalControl;
-    @GuardedBy("mLock")
-    private float mCurrentAmplitude;
+
+    // Vibrator state variables that are updated from synchronized blocks but can be read anytime
+    // for a snippet of the current known vibrator state/info.
+    private volatile VibratorInfo mVibratorInfo;
+    private volatile boolean mVibratorInfoLoadSuccessful;
+    private volatile boolean mIsVibrating;
+    private volatile boolean mIsUnderExternalControl;
+    private volatile float mCurrentAmplitude;
 
     /** Listener for vibration completion callbacks from native. */
     public interface OnVibrationCompleteListener {
@@ -86,35 +87,39 @@
 
     /** Register state listener for this vibrator. */
     public boolean registerVibratorStateListener(IVibratorStateListener listener) {
-        synchronized (mLock) {
-            final long token = Binder.clearCallingIdentity();
-            try {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            // Register the listener and send the first state atomically, to avoid potentially
+            // out of order broadcasts in between.
+            synchronized (mLock) {
                 if (!mVibratorStateListeners.register(listener)) {
                     return false;
                 }
                 // Notify its callback after new client registered.
-                notifyStateListenerLocked(listener);
-                return true;
-            } finally {
-                Binder.restoreCallingIdentity(token);
+                notifyStateListener(listener, mIsVibrating);
             }
+            return true;
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
     }
 
     /** Remove registered state listener for this vibrator. */
     public boolean unregisterVibratorStateListener(IVibratorStateListener listener) {
-        synchronized (mLock) {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                return mVibratorStateListeners.unregister(listener);
-            } finally {
-                Binder.restoreCallingIdentity(token);
-            }
+        final long token = Binder.clearCallingIdentity();
+        try {
+            return mVibratorStateListeners.unregister(listener);
+        } finally {
+            Binder.restoreCallingIdentity(token);
         }
     }
 
     /** Reruns the query to the vibrator to load the {@link VibratorInfo}, if not yet successful. */
     public void reloadVibratorInfoIfNeeded() {
+        // Early check outside lock, for quick return.
+        if (mVibratorInfoLoadSuccessful) {
+            return;
+        }
         synchronized (mLock) {
             if (mVibratorInfoLoadSuccessful) {
                 return;
@@ -132,16 +137,12 @@
 
     /** Checks if the {@link VibratorInfo} was loaded from the vibrator hardware successfully. */
     boolean isVibratorInfoLoadSuccessful() {
-        synchronized (mLock) {
-            return mVibratorInfoLoadSuccessful;
-        }
+        return mVibratorInfoLoadSuccessful;
     }
 
     /** Return the {@link VibratorInfo} representing the vibrator controlled by this instance. */
     public VibratorInfo getVibratorInfo() {
-        synchronized (mLock) {
-            return mVibratorInfo;
-        }
+        return mVibratorInfo;
     }
 
     /**
@@ -151,9 +152,7 @@
      * automatically notified to any registered {@link IVibratorStateListener} on change.
      */
     public boolean isVibrating() {
-        synchronized (mLock) {
-            return mIsVibrating;
-        }
+        return mIsVibrating;
     }
 
     /**
@@ -168,16 +167,12 @@
      * <p>If {@link #isVibrating()} is false then this will be zero.
      */
     public float getCurrentAmplitude() {
-        synchronized (mLock) {
-            return mCurrentAmplitude;
-        }
+        return mCurrentAmplitude;
     }
 
     /** Return {@code true} if this vibrator is under external control, false otherwise. */
     public boolean isUnderExternalControl() {
-        synchronized (mLock) {
-            return mIsUnderExternalControl;
-        }
+        return mIsUnderExternalControl;
     }
 
     /**
@@ -187,14 +182,14 @@
      * @return true if this vibrator has this capability, false otherwise
      */
     public boolean hasCapability(long capability) {
-        synchronized (mLock) {
-            return mVibratorInfo.hasCapability(capability);
-        }
+        return mVibratorInfo.hasCapability(capability);
     }
 
     /** Return {@code true} if the underlying vibrator is currently available, false otherwise. */
     public boolean isAvailable() {
-        return mNativeWrapper.isAvailable();
+        synchronized (mLock) {
+            return mNativeWrapper.isAvailable();
+        }
     }
 
     /**
@@ -203,10 +198,10 @@
      * <p>This will affect the state of {@link #isUnderExternalControl()}.
      */
     public void setExternalControl(boolean externalControl) {
+        if (!mVibratorInfo.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) {
+            return;
+        }
         synchronized (mLock) {
-            if (!mVibratorInfo.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) {
-                return;
-            }
             mIsUnderExternalControl = externalControl;
             mNativeWrapper.setExternalControl(externalControl);
         }
@@ -217,10 +212,10 @@
      * if given {@code effect} is {@code null}.
      */
     public void updateAlwaysOn(int id, @Nullable PrebakedSegment prebaked) {
+        if (!mVibratorInfo.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
+            return;
+        }
         synchronized (mLock) {
-            if (!mVibratorInfo.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
-                return;
-            }
             if (prebaked == null) {
                 mNativeWrapper.alwaysOnDisable(id);
             } else {
@@ -256,7 +251,7 @@
             long duration = mNativeWrapper.on(milliseconds, vibrationId);
             if (duration > 0) {
                 mCurrentAmplitude = -1;
-                notifyVibratorOnLocked();
+                notifyListenerOnVibrating(true);
             }
             return duration;
         }
@@ -277,7 +272,7 @@
                     prebaked.getEffectStrength(), vibrationId);
             if (duration > 0) {
                 mCurrentAmplitude = -1;
-                notifyVibratorOnLocked();
+                notifyListenerOnVibrating(true);
             }
             return duration;
         }
@@ -293,14 +288,14 @@
      * do not support the input or a negative number if the operation failed.
      */
     public long on(PrimitiveSegment[] primitives, long vibrationId) {
+        if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
+            return 0;
+        }
         synchronized (mLock) {
-            if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
-                return 0;
-            }
             long duration = mNativeWrapper.compose(primitives, vibrationId);
             if (duration > 0) {
                 mCurrentAmplitude = -1;
-                notifyVibratorOnLocked();
+                notifyListenerOnVibrating(true);
             }
             return duration;
         }
@@ -315,15 +310,15 @@
      * @return The duration of the effect playing, or 0 if unsupported.
      */
     public long on(RampSegment[] primitives, long vibrationId) {
+        if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) {
+            return 0;
+        }
         synchronized (mLock) {
-            if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) {
-                return 0;
-            }
             int braking = mVibratorInfo.getDefaultBraking();
             long duration = mNativeWrapper.composePwle(primitives, braking, vibrationId);
             if (duration > 0) {
                 mCurrentAmplitude = -1;
-                notifyVibratorOnLocked();
+                notifyListenerOnVibrating(true);
             }
             return duration;
         }
@@ -334,7 +329,7 @@
         synchronized (mLock) {
             mNativeWrapper.off();
             mCurrentAmplitude = 0;
-            notifyVibratorOffLocked();
+            notifyListenerOnVibrating(false);
         }
     }
 
@@ -349,51 +344,31 @@
 
     @Override
     public String toString() {
-        synchronized (mLock) {
-            return "VibratorController{"
-                    + "mVibratorInfo=" + mVibratorInfo
-                    + ", mVibratorInfoLoadSuccessful=" + mVibratorInfoLoadSuccessful
-                    + ", mIsVibrating=" + mIsVibrating
-                    + ", mCurrentAmplitude=" + mCurrentAmplitude
-                    + ", mIsUnderExternalControl=" + mIsUnderExternalControl
-                    + ", mVibratorStateListeners count="
-                    + mVibratorStateListeners.getRegisteredCallbackCount()
-                    + '}';
-        }
+        return "VibratorController{"
+                + "mVibratorInfo=" + mVibratorInfo
+                + ", mVibratorInfoLoadSuccessful=" + mVibratorInfoLoadSuccessful
+                + ", mIsVibrating=" + mIsVibrating
+                + ", mCurrentAmplitude=" + mCurrentAmplitude
+                + ", mIsUnderExternalControl=" + mIsUnderExternalControl
+                + ", mVibratorStateListeners count="
+                + mVibratorStateListeners.getRegisteredCallbackCount()
+                + '}';
     }
 
     @GuardedBy("mLock")
-    private void notifyVibratorOnLocked() {
-        if (!mIsVibrating) {
-            mIsVibrating = true;
-            notifyStateListenersLocked();
+    private void notifyListenerOnVibrating(boolean isVibrating) {
+        if (mIsVibrating != isVibrating) {
+            mIsVibrating = isVibrating;
+            // The broadcast method is safe w.r.t. register/unregister listener methods, but lock
+            // is required here to guarantee delivery order.
+            mVibratorStateListeners.broadcast(
+                    listener -> notifyStateListener(listener, isVibrating));
         }
     }
 
-    @GuardedBy("mLock")
-    private void notifyVibratorOffLocked() {
-        if (mIsVibrating) {
-            mIsVibrating = false;
-            notifyStateListenersLocked();
-        }
-    }
-
-    @GuardedBy("mLock")
-    private void notifyStateListenersLocked() {
-        final int length = mVibratorStateListeners.beginBroadcast();
+    private void notifyStateListener(IVibratorStateListener listener, boolean isVibrating) {
         try {
-            for (int i = 0; i < length; i++) {
-                notifyStateListenerLocked(mVibratorStateListeners.getBroadcastItem(i));
-            }
-        } finally {
-            mVibratorStateListeners.finishBroadcast();
-        }
-    }
-
-    @GuardedBy("mLock")
-    private void notifyStateListenerLocked(IVibratorStateListener listener) {
-        try {
-            listener.onVibrating(mIsVibrating);
+            listener.onVibrating(isVibrating);
         } catch (RemoteException | RuntimeException e) {
             Slog.e(TAG, "Vibrator state listener failed to call", e);
         }
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 3a3ce5b..9717201 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -229,7 +229,7 @@
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SCREEN_OFF);
-        context.registerReceiver(mIntentReceiver, filter);
+        context.registerReceiver(mIntentReceiver, filter, Context.RECEIVER_NOT_EXPORTED);
 
         injector.addService(EXTERNAL_VIBRATOR_SERVICE, new ExternalVibratorService());
     }
@@ -341,7 +341,7 @@
             if (!isEffectValid(effect)) {
                 return false;
             }
-            attrs = fixupVibrationAttributes(attrs);
+            attrs = fixupVibrationAttributes(attrs, effect);
             synchronized (mLock) {
                 SparseArray<PrebakedSegment> effects = fixupAlwaysOnEffectsLocked(effect);
                 if (effects == null) {
@@ -385,12 +385,15 @@
             if (!isEffectValid(effect)) {
                 return null;
             }
-            attrs = fixupVibrationAttributes(attrs);
+            attrs = fixupVibrationAttributes(attrs, effect);
             Vibration vib = new Vibration(token, mNextVibrationId.getAndIncrement(), effect, attrs,
                     uid, opPkg, reason);
             fillVibrationFallbacks(vib, effect);
 
             synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Starting vibrate for vibration  " + vib.id);
+                }
                 Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(vib);
                 if (ignoreStatus != null) {
                     endVibrationLocked(vib, ignoreStatus);
@@ -498,6 +501,9 @@
     @VisibleForTesting
     void updateServiceState() {
         synchronized (mLock) {
+            if (DEBUG) {
+                Slog.d(TAG, "Updating device state...");
+            }
             boolean inputDevicesChanged = mInputDeviceDelegate.updateInputDeviceVibrators(
                     mVibrationSettings.shouldVibrateInputDevices());
 
@@ -611,6 +617,9 @@
         Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
         try {
             Vibration vib = mCurrentVibration.getVibration();
+            if (DEBUG) {
+                Slog.d(TAG, "Reporting vibration " + vib.id + " finished with status " + status);
+            }
             endVibrationLocked(vib, status);
             finishAppOpModeLocked(vib.uid, vib.opPkg);
         } finally {
@@ -886,21 +895,32 @@
      * Return new {@link VibrationAttributes} that only applies flags that this user has permissions
      * to use.
      */
-    private VibrationAttributes fixupVibrationAttributes(@Nullable VibrationAttributes attrs) {
+    @NonNull
+    private VibrationAttributes fixupVibrationAttributes(@Nullable VibrationAttributes attrs,
+            CombinedVibration effect) {
         if (attrs == null) {
             attrs = DEFAULT_ATTRIBUTES;
         }
+        int usage = attrs.getUsage();
+        if ((usage == VibrationAttributes.USAGE_UNKNOWN) && effect.isHapticFeedbackCandidate()) {
+            usage = VibrationAttributes.USAGE_TOUCH;
+        }
+        int flags = attrs.getFlags();
         if (attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY)) {
             if (!(hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
                     || hasPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
                     || hasPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING))) {
-                final int flags = attrs.getFlags()
-                        & ~VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
-                attrs = new VibrationAttributes.Builder(attrs)
-                        .setFlags(flags, attrs.getFlags()).build();
+                // Remove bypass policy flag from attributes if the app does not have permissions.
+                flags &= ~VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY;
             }
         }
-        return attrs;
+        if ((usage == attrs.getUsage()) && (flags == attrs.getFlags())) {
+            return attrs;
+        }
+        return new VibrationAttributes.Builder(attrs)
+                .setUsage(usage)
+                .setFlags(flags, attrs.getFlags())
+                .build();
     }
 
     @GuardedBy("mLock")
@@ -1062,11 +1082,17 @@
                 Slog.d(TAG, "Vibrators released after finished vibration");
             }
             synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Processing vibrators released callback");
+                }
                 mCurrentVibration = null;
                 if (mNextVibration != null) {
                     VibrationThread vibThread = mNextVibration;
                     mNextVibration = null;
-                    startVibrationThreadLocked(vibThread);
+                    Vibration.Status status = startVibrationThreadLocked(vibThread);
+                    if (status != Vibration.Status.RUNNING) {
+                        endVibrationLocked(vibThread.getVibration(), status);
+                    }
                 }
             }
         }
@@ -1248,6 +1274,9 @@
         void dumpText(PrintWriter pw) {
             pw.println("Vibrator Manager Service:");
             synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Dumping vibrator manager service to text...");
+                }
                 pw.println("  mVibrationSettings:");
                 pw.println("    " + mVibrationSettings);
                 pw.println();
@@ -1290,6 +1319,9 @@
             final ProtoOutputStream proto = new ProtoOutputStream(fd);
 
             synchronized (mLock) {
+                if (DEBUG) {
+                    Slog.d(TAG, "Dumping vibrator manager service to proto...");
+                }
                 mVibrationSettings.dumpProto(proto);
                 if (mCurrentVibration != null) {
                     mCurrentVibration.getVibration().getDebugInfo().dumpProto(proto,
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 8644d1e..ffc70da 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1376,9 +1376,7 @@
     /** Whether we should prepare a transition for this {@link ActivityRecord} parent change. */
     private boolean shouldStartChangeTransition(
             @Nullable TaskFragment newParent, @Nullable TaskFragment oldParent) {
-        if (mWmService.mDisableTransitionAnimation
-                || mDisplayContent == null || newParent == null || oldParent == null
-                || getSurfaceControl() == null || !isVisible() || !isVisibleRequested()) {
+        if (newParent == null || oldParent == null || !canStartChangeTransition()) {
             return false;
         }
 
@@ -2755,14 +2753,13 @@
             return false;
         }
 
-        boolean isKeyguardLocked = mAtmService.isKeyguardLocked();
         boolean isCurrentAppLocked =
                 mAtmService.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
         final TaskDisplayArea taskDisplayArea = getDisplayArea();
         boolean hasRootPinnedTask = taskDisplayArea != null && taskDisplayArea.hasPinnedTask();
         // Don't return early if !isNotLocked, since we want to throw an exception if the activity
         // is in an incorrect state
-        boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
+        boolean isNotLockedOrOnKeyguard = !isKeyguardLocked() && !isCurrentAppLocked;
 
         // We don't allow auto-PiP when something else is already pipped.
         if (beforeStopping && hasRootPinnedTask) {
@@ -3161,7 +3158,7 @@
                 // If the current activity is not opaque, we need to make sure the visibilities of
                 // activities be updated, they may be seen by users.
                 ensureVisibility = true;
-            } else if (mTaskSupervisor.getKeyguardController().isKeyguardLocked()
+            } else if (isKeyguardLocked()
                     && mTaskSupervisor.getKeyguardController().topActivityOccludesKeyguard(this)) {
                 // Ensure activity visibilities and update lockscreen occluded/dismiss state when
                 // finishing the top activity that occluded keyguard. So that, the
@@ -3990,6 +3987,11 @@
         });
     }
 
+    boolean isKeyguardLocked() {
+        return (mDisplayContent != null) ? mDisplayContent.isKeyguardLocked() :
+                mRootWindowContainer.getDefaultDisplay().isKeyguardLocked();
+    }
+
     void checkKeyguardFlagsChanged() {
         final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
         final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
@@ -5179,7 +5181,7 @@
     void notifyUnknownVisibilityLaunchedForKeyguardTransition() {
         // No display activities never add a window, so there is no point in waiting them for
         // relayout.
-        if (noDisplay || !mTaskSupervisor.getKeyguardController().isKeyguardLocked()) {
+        if (noDisplay || !isKeyguardLocked()) {
             return;
         }
 
@@ -5967,10 +5969,11 @@
         // because it may be a trampoline.
         if (!wasTaskVisible && mStartingData != null && !finishing && !mLaunchedFromBubble
                 && !mDisplayContent.mAppTransition.isReady()
-                && !mDisplayContent.mAppTransition.isRunning()) {
+                && !mDisplayContent.mAppTransition.isRunning()
+                && mDisplayContent.isNextTransitionForward()) {
             // The pending transition state will be cleared after the transition is started, so
             // save the state for launching the client later (used by LaunchActivityItem).
-            mStartingData.mIsTransitionForward = mDisplayContent.isNextTransitionForward();
+            mStartingData.mIsTransitionForward = true;
             mDisplayContent.executeAppTransition();
         }
     }
@@ -6219,15 +6222,15 @@
     public boolean inputDispatchingTimedOut(String reason, int windowPid) {
         ActivityRecord anrActivity;
         WindowProcessController anrApp;
-        boolean windowFromSameProcessAsActivity;
+        boolean blameActivityProcess;
         synchronized (mAtmService.mGlobalLock) {
             anrActivity = getWaitingHistoryRecordLocked();
             anrApp = app;
-            windowFromSameProcessAsActivity =
-                    !hasProcess() || app.getPid() == windowPid || windowPid == INVALID_PID;
+            blameActivityProcess =  hasProcess()
+                    && (app.getPid() == windowPid || windowPid == INVALID_PID);
         }
 
-        if (windowFromSameProcessAsActivity) {
+        if (blameActivityProcess) {
             return mAtmService.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
                     anrActivity.shortComponentName, anrActivity.info.applicationInfo,
                     shortComponentName, app, false, reason);
diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java
index 210b0ae..ecc8587 100644
--- a/services/core/java/com/android/server/wm/ActivityStartController.java
+++ b/services/core/java/com/android/server/wm/ActivityStartController.java
@@ -496,11 +496,13 @@
      * @param activityIntent intent to start the activity.
      * @param activityOptions ActivityOptions to start the activity with.
      * @param resultTo the caller activity
+     * @param callingUid the caller uid
+     * @param callingPid the caller pid
      * @return the start result.
      */
     int startActivityInTaskFragment(@NonNull TaskFragment taskFragment,
             @NonNull Intent activityIntent, @Nullable Bundle activityOptions,
-            @Nullable IBinder resultTo) {
+            @Nullable IBinder resultTo, int callingUid, int callingPid) {
         final ActivityRecord caller =
                 resultTo != null ? ActivityRecord.forTokenLocked(resultTo) : null;
         return obtainStarter(activityIntent, "startActivityInTaskFragment")
@@ -508,8 +510,8 @@
                 .setInTaskFragment(taskFragment)
                 .setResultTo(resultTo)
                 .setRequestCode(-1)
-                .setCallingUid(Binder.getCallingUid())
-                .setCallingPid(Binder.getCallingPid())
+                .setCallingUid(callingUid)
+                .setCallingPid(callingPid)
                 .setUserId(caller != null ? caller.mUserId : mService.getCurrentUserId())
                 .execute();
     }
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 73a783e..bb7434d 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2784,8 +2784,8 @@
         // If it exist, we need to reparent target root task from TDA to launch root task.
         final TaskDisplayArea tda = mTargetRootTask.getDisplayArea();
         final Task launchRootTask = tda.getLaunchRootTask(mTargetRootTask.getWindowingMode(),
-                mTargetRootTask.getActivityType(), null /** options */,
-                mSourceRootTask, 0 /** launchFlags */);
+                mTargetRootTask.getActivityType(), null /** options */, mSourceRootTask,
+                mLaunchFlags);
         // If target root task is created by organizer, let organizer handle reparent itself.
         if (!mTargetRootTask.mCreatedByOrganizer && launchRootTask != null
                 && launchRootTask != mTargetRootTask) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 7fa9861..e38e9c1 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -126,35 +126,6 @@
     }
 
     /**
-     * Sleep tokens cause the activity manager to put the top activity to sleep.
-     * They are used by components such as dreams that may hide and block interaction
-     * with underlying activities.
-     * The Acquirer provides an interface that encapsulates the underlying work, so the user does
-     * not need to handle the token by him/herself.
-     */
-    public interface SleepTokenAcquirer {
-
-        /**
-         * Acquires a sleep token.
-         * @param displayId The display to apply to.
-         */
-        void acquire(int displayId);
-
-        /**
-         * Releases the sleep token.
-         * @param displayId The display to apply to.
-         */
-        void release(int displayId);
-    }
-
-    /**
-     * Creates a sleep token acquirer for the specified display with the specified tag.
-     *
-     * @param tag A string identifying the purpose (eg. "Dream").
-     */
-    public abstract SleepTokenAcquirer createSleepTokenAcquirer(@NonNull String tag);
-
-    /**
      * Returns home activity for the specified user.
      *
      * @param userId ID of the user or {@link android.os.UserHandle#USER_ALL}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 9455ce6..e4ed04de 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -2799,7 +2799,10 @@
                 mH.sendMessage(msg);
             }
             try {
-                mKeyguardController.setKeyguardShown(keyguardShowing, aodShowing);
+                mRootWindowContainer.forAllDisplays(displayContent -> {
+                    mKeyguardController.setKeyguardShown(displayContent.getDisplayId(),
+                            keyguardShowing, aodShowing);
+                });
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -3359,7 +3362,9 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
-                mKeyguardController.keyguardGoingAway(flags);
+                mRootWindowContainer.forAllDisplays(displayContent -> {
+                    mKeyguardController.keyguardGoingAway(displayContent.getDisplayId(), flags);
+                });
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -3442,7 +3447,7 @@
             }
         };
 
-        if (isKeyguardLocked()) {
+        if (r.isKeyguardLocked()) {
             // If the keyguard is showing or occluded, then try and dismiss it before
             // entering picture-in-picture (this will prompt the user to authenticate if the
             // device is currently locked).
@@ -3787,8 +3792,8 @@
         mRecentTasks.notifyTaskPersisterLocked(task, flush);
     }
 
-    boolean isKeyguardLocked() {
-        return mKeyguardController.isKeyguardLocked();
+    boolean isKeyguardLocked(int displayId) {
+        return mKeyguardController.isKeyguardLocked(displayId);
     }
 
     /**
@@ -4539,17 +4544,25 @@
                 reason);
     }
 
-    final class SleepTokenAcquirerImpl implements ActivityTaskManagerInternal.SleepTokenAcquirer {
+    /**
+     * Sleep tokens cause the activity manager to put the top activity to sleep.
+     * They are used by components such as dreams that may hide and block interaction
+     * with underlying activities.
+     */
+    final class SleepTokenAcquirer {
         private final String mTag;
         private final SparseArray<RootWindowContainer.SleepToken> mSleepTokens =
                 new SparseArray<>();
 
-        SleepTokenAcquirerImpl(@NonNull String tag) {
+        SleepTokenAcquirer(@NonNull String tag) {
             mTag = tag;
         }
 
-        @Override
-        public void acquire(int displayId) {
+        /**
+         * Acquires a sleep token.
+         * @param displayId The display to apply to.
+         */
+        void acquire(int displayId) {
             synchronized (mGlobalLock) {
                 if (!mSleepTokens.contains(displayId)) {
                     mSleepTokens.append(displayId,
@@ -4559,8 +4572,11 @@
             }
         }
 
-        @Override
-        public void release(int displayId) {
+        /**
+         * Releases the sleep token.
+         * @param displayId The display to apply to.
+         */
+        void release(int displayId) {
             synchronized (mGlobalLock) {
                 final RootWindowContainer.SleepToken token = mSleepTokens.get(displayId);
                 if (token != null) {
@@ -5250,12 +5266,6 @@
 
     final class LocalService extends ActivityTaskManagerInternal {
         @Override
-        public SleepTokenAcquirer createSleepTokenAcquirer(@NonNull String tag) {
-            Objects.requireNonNull(tag);
-            return new SleepTokenAcquirerImpl(tag);
-        }
-
-        @Override
         public ComponentName getHomeActivityForUser(int userId) {
             synchronized (mGlobalLock) {
                 final ActivityRecord homeActivity =
@@ -6035,7 +6045,7 @@
                 final long ident = Binder.clearCallingIdentity();
                 try {
                     if (mAmInternal.shouldConfirmCredentials(userId)) {
-                        if (mKeyguardController.isKeyguardLocked()) {
+                        if (mKeyguardController.isKeyguardLocked(DEFAULT_DISPLAY)) {
                             // Showing launcher to avoid user entering credential twice.
                             startHomeActivity(currentUserId, "notifyLockedProfile");
                         }
diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java
index f947773..721907c 100644
--- a/services/core/java/com/android/server/wm/AppTransitionController.java
+++ b/services/core/java/com/android/server/wm/AppTransitionController.java
@@ -65,7 +65,10 @@
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_SPLASH_SCREEN;
 import static com.android.server.wm.ActivityTaskManagerInternal.APP_TRANSITION_WINDOWS_DRAWN;
 import static com.android.server.wm.AppTransition.isNormalTransit;
+import static com.android.server.wm.NonAppWindowAnimationAdapter.shouldAttachNavBarToApp;
+import static com.android.server.wm.NonAppWindowAnimationAdapter.shouldStartNonAppWindowAnimationsForKeyguardExit;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
+import static com.android.server.wm.WallpaperAnimationAdapter.shouldStartWallpaperAnimation;
 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -173,6 +176,9 @@
         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady");
 
         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "**** GOOD TO GO");
+        // TODO(b/205335975): Remove window which stuck in animatingExit status. Find actual cause.
+        mDisplayContent.forAllWindows(WindowState::cleanupAnimatingExitWindow,
+                true /* traverseTopToBottom */);
         // TODO(new-app-transition): Remove code using appTransition.getAppTransition()
         final AppTransition appTransition = mDisplayContent.mAppTransition;
 
@@ -529,18 +535,9 @@
         // Having {@code transit} of those types doesn't mean it will contain non-app windows, but
         // non-app windows will only be included with those transition types. And we don't currently
         // have any use case of those for TaskFragment transition.
-        // @see NonAppWindowAnimationAdapter#startNonAppWindowAnimations
-        if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
-                || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER
-                || transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT
-                || transit == TRANSIT_OLD_WALLPAPER_CLOSE) {
-            return true;
-        }
-
-        // Check if the wallpaper is going to participate in the transition. We don't want to have
-        // the client to animate the wallpaper windows.
-        // @see WallpaperAnimationAdapter#startWallpaperAnimations
-        return mDisplayContent.mWallpaperController.isWallpaperVisible();
+        return shouldStartNonAppWindowAnimationsForKeyguardExit(transit)
+                || shouldAttachNavBarToApp(mService, mDisplayContent, transit)
+                || shouldStartWallpaperAnimation(mDisplayContent);
     }
 
     /**
@@ -596,7 +593,7 @@
             }
             // We don't want the organizer to handle transition of non-embedded activity of other
             // app.
-            if (r.getUid() != rootActivity.getUid() && !r.isEmbedded()) {
+            if (r.getUid() != task.effectiveUid && !r.isEmbedded()) {
                 leafTask = null;
                 break;
             }
diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java
index 7485a1e..132396b 100644
--- a/services/core/java/com/android/server/wm/DisplayArea.java
+++ b/services/core/java/com/android/server/wm/DisplayArea.java
@@ -560,7 +560,7 @@
                 // Ignore the orientation of keyguard if it is going away or is not showing while
                 // the device is fully awake. In other words, use the orientation of keyguard if
                 // its window is visible while the device is going to sleep or is sleeping.
-                if (!mWmService.mAtmService.isKeyguardLocked()
+                if (!mDisplayContent.isKeyguardLocked()
                         && mDisplayContent.getDisplayPolicy().isAwake()
                         // Device is not going to sleep.
                         && policy.okToAnimate(true /* ignoreScreenOn */)) {
@@ -586,7 +586,11 @@
         };
 
         Tokens(WindowManagerService wms, Type type, String name) {
-            super(wms, type, name, FEATURE_WINDOW_TOKENS);
+            this(wms, type, name, FEATURE_WINDOW_TOKENS);
+        }
+
+        Tokens(WindowManagerService wms, Type type, String name, int featureId) {
+            super(wms, type, name, featureId);
         }
 
         void addChild(WindowToken token) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 7a38554..68eff9a 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -34,6 +34,7 @@
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
 import static android.os.Build.VERSION_CODES.N;
+import static android.os.Process.SYSTEM_UID;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.util.DisplayMetrics.DENSITY_DEFAULT;
 import static android.util.RotationUtils.deltaRotation;
@@ -43,6 +44,8 @@
 import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
+import static android.view.Display.STATE_UNKNOWN;
+import static android.view.Display.isSuspendedState;
 import static android.view.InsetsState.ITYPE_IME;
 import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
@@ -61,6 +64,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
+import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
 import static android.view.WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN;
@@ -78,6 +82,7 @@
 import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
+import static android.window.DisplayAreaOrganizer.FEATURE_IME;
 import static android.window.DisplayAreaOrganizer.FEATURE_ROOT;
 import static android.window.DisplayAreaOrganizer.FEATURE_WINDOWED_MAGNIFICATION;
 
@@ -217,6 +222,7 @@
 import android.view.WindowManager;
 import android.view.WindowManager.DisplayImePolicy;
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
+import android.window.DisplayWindowPolicyController;
 import android.window.IDisplayAreaOrganizer;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -315,11 +321,6 @@
      */
     private Rect mLastMirroredDisplayAreaBounds = null;
 
-    /**
-     * The last state of the display.
-     */
-    private int mLastDisplayState;
-
     // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
     // on the IME target. We mainly have this container grouping so we can keep track of all the IME
     // window containers together and move them in-sync if/when needed. We use a subclass of
@@ -632,7 +633,8 @@
     @interface InputMethodTarget {}
 
     /** The surface parent of the IME container. */
-    private SurfaceControl mInputMethodSurfaceParent;
+    @VisibleForTesting
+    SurfaceControl mInputMethodSurfaceParent;
 
     /** The screenshot IME surface to place on the task while transitioning to the next task. */
     SurfaceControl mImeScreenshot;
@@ -662,7 +664,7 @@
     /** All tokens used to put activities on this root task to sleep (including mOffToken) */
     final ArrayList<RootWindowContainer.SleepToken> mAllSleepTokens = new ArrayList<>();
     /** The token acquirer to put root tasks on the display to sleep */
-    private final ActivityTaskManagerInternal.SleepTokenAcquirer mOffTokenAcquirer;
+    private final ActivityTaskManagerService.SleepTokenAcquirer mOffTokenAcquirer;
 
     private boolean mSleeping;
 
@@ -694,6 +696,14 @@
     // well and thus won't change the top resumed / focused record
     boolean mDontMoveToTop;
 
+    /**
+     * The policy controller of the windows that can be displayed on the virtual display.
+     *
+     * @see DisplayWindowPolicyController
+     */
+    @Nullable
+    DisplayWindowPolicyController mDisplayWindowPolicyController;
+
     private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
         WindowStateAnimator winAnimator = w.mWinAnimator;
         final ActivityRecord activity = w.mActivityRecord;
@@ -1629,11 +1639,6 @@
             // to cover the activity configuration change.
             return false;
         }
-        if (r.attachedToProcess() && mayImeShowOnLaunchingActivity(r)) {
-            // Currently it is unknown that when will IME window be ready. Reject the case to
-            // avoid flickering by showing IME in inconsistent orientation.
-            return false;
-        }
         if (checkOpening) {
             if (!mAppTransition.isTransitionSet() || !mOpeningApps.contains(r)) {
                 // Apply normal rotation animation in case of the activity set different requested
@@ -2737,6 +2742,9 @@
             if (newDisplayInfo != null) {
                 mDisplayInfo.copyFrom(newDisplayInfo);
             }
+
+            mDisplayWindowPolicyController =
+                    displayManagerInternal.getDisplayWindowPolicyController(mDisplayId);
         }
 
         updateBaseDisplayMetrics(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight,
@@ -2819,8 +2827,14 @@
         mBaseDisplayDensity = baseDensity;
 
         if (mMaxUiWidth > 0 && mBaseDisplayWidth > mMaxUiWidth) {
-            mBaseDisplayHeight = (mMaxUiWidth * mBaseDisplayHeight) / mBaseDisplayWidth;
+            final float ratio = mMaxUiWidth / (float) mBaseDisplayWidth;
+            mBaseDisplayHeight = (int) (mBaseDisplayHeight * ratio);
             mBaseDisplayWidth = mMaxUiWidth;
+            if (!mIsDensityForced) {
+                // Update the density proportionally so the size of the UI elements won't change
+                // from the user's perspective.
+                mBaseDisplayDensity = (int) (mBaseDisplayDensity * ratio);
+            }
 
             if (DEBUG_DISPLAY) {
                 Slog.v(TAG_WM, "Applying config restraints:" + mBaseDisplayWidth + "x"
@@ -2877,6 +2891,13 @@
 
     /** If the given width and height equal to initial size, the setting will be cleared. */
     void setForcedSize(int width, int height) {
+        // Can't force size higher than the maximal allowed
+        if (mMaxUiWidth > 0 && width > mMaxUiWidth) {
+            final float ratio = mMaxUiWidth / (float) width;
+            height = (int) (height * ratio);
+            width = mMaxUiWidth;
+        }
+
         mIsSizeForced = mInitialDisplayWidth != width || mInitialDisplayHeight != height;
         if (mIsSizeForced) {
             // Set some sort of reasonable bounds on the size of the display that we will try
@@ -3418,6 +3439,10 @@
         mInputMonitor.dump(pw, "  ");
         pw.println();
         mInsetsStateController.dump(prefix, pw);
+        if (mDisplayWindowPolicyController != null) {
+            pw.println();
+            mDisplayWindowPolicyController.dump(prefix, pw);
+        }
     }
 
     @Override
@@ -3831,6 +3856,10 @@
     }
 
     boolean shouldImeAttachedToApp() {
+        if (mImeWindowsContainer.isOrganized()) {
+            return false;
+        }
+
         // Force attaching IME to the display when magnifying, or it would be magnified with
         // target app together.
         final boolean allowAttachToApp = (mMagnificationSpec == null);
@@ -3959,8 +3988,9 @@
         mImeLayeringTarget = target;
 
         // 1. Reparent the IME container window to the target root DA to get the correct bounds and
-        // config. (Only happens when the target window is in a different root DA)
-        if (target != null) {
+        // config. Only happens when the target window is in a different root DA and ImeContainer
+        // is not organized (see FEATURE_IME and updateImeParent).
+        if (target != null && !mImeWindowsContainer.isOrganized()) {
             RootDisplayArea targetRoot = target.getRootDisplayArea();
             if (targetRoot != null && targetRoot != mImeWindowsContainer.getRootDisplayArea()) {
                 // Reposition the IME container to the target root to get the correct bounds and
@@ -4144,6 +4174,16 @@
     }
 
     void updateImeParent() {
+        if (mImeWindowsContainer.isOrganized()) {
+            if (DEBUG_INPUT_METHOD) {
+                Slog.i(TAG_WM, "ImeContainer is organized. Skip updateImeParent.");
+            }
+            // Leave the ImeContainer where the DisplayAreaPolicy placed it.
+            // FEATURE_IME is organized by vendor so they are responible for placing the surface.
+            mInputMethodSurfaceParent = null;
+            return;
+        }
+
         final SurfaceControl newParent = computeImeParent();
         if (newParent != null && newParent != mInputMethodSurfaceParent) {
             mInputMethodSurfaceParent = newParent;
@@ -4255,7 +4295,7 @@
             boolean subtle) {
         final WindowManagerPolicy policy = mWmService.mPolicy;
         forAllWindows(w -> {
-            if (w.mActivityRecord == null && policy.canBeHiddenByKeyguardLw(w)
+            if (w.mActivityRecord == null && w.canBeHiddenByKeyguard()
                     && w.wouldBeVisibleIfPolicyIgnored() && !w.isVisible()) {
                 w.startAnimation(policy.createHiddenByKeyguardExit(
                         onWallpaper, goingToShade, subtle));
@@ -4626,12 +4666,9 @@
         mWmService.requestTraversal();
     }
 
+    @Override
     boolean okToDisplay() {
-        return okToDisplay(false);
-    }
-
-    boolean okToDisplay(boolean ignoreFrozen) {
-        return okToDisplay(ignoreFrozen, false /* ignoreScreenOn */);
+        return okToDisplay(false /* ignoreFrozen */, false /* ignoreScreenOn */);
     }
 
     boolean okToDisplay(boolean ignoreFrozen, boolean ignoreScreenOn) {
@@ -4643,18 +4680,12 @@
         return mDisplayInfo.state == Display.STATE_ON;
     }
 
-    boolean okToAnimate() {
-        return okToAnimate(false);
-    }
-
-    boolean okToAnimate(boolean ignoreFrozen) {
-        return okToAnimate(ignoreFrozen, false /* ignoreScreenOn */);
-    }
-
+    @Override
     boolean okToAnimate(boolean ignoreFrozen, boolean ignoreScreenOn) {
         return okToDisplay(ignoreFrozen, ignoreScreenOn)
                 && (mDisplayId != DEFAULT_DISPLAY
-                || mWmService.mPolicy.okToAnimate(ignoreScreenOn));
+                || mWmService.mPolicy.okToAnimate(ignoreScreenOn))
+                && getDisplayPolicy().isScreenOnFully();
     }
 
     static final class TaskForResizePointSearchResult implements Predicate<Task> {
@@ -4750,7 +4781,7 @@
         boolean mNeedsLayer = false;
 
         ImeContainer(WindowManagerService wms) {
-            super(wms, Type.ABOVE_TASKS, "ImeContainer");
+            super(wms, Type.ABOVE_TASKS, "ImeContainer", FEATURE_IME);
         }
 
         public void setNeedsLayer() {
@@ -4784,7 +4815,10 @@
             // WindowState#applyImeWindowsIfNeeded} in case of any state mismatch.
             return dc.mImeLayeringTarget != null
                     && (!dc.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
-                             || dc.mImeLayeringTarget.getTask() == null);
+                             || dc.mImeLayeringTarget.getTask() == null)
+                    // Make sure that the IME window won't be skipped to report that it has
+                    // completed the orientation change.
+                    && !dc.mWmService.mDisplayFrozen;
         }
 
         /** Like {@link #forAllWindows}, but ignores {@link #skipImeWindowsDuringTraversal} */
@@ -4811,6 +4845,12 @@
             super.assignRelativeLayer(t, relativeTo, layer, forceUpdate);
             mNeedsLayer = false;
         }
+
+        @Override
+        void setOrganizer(IDisplayAreaOrganizer organizer, boolean skipDisplayAreaAppeared) {
+            super.setOrganizer(organizer, skipDisplayAreaAppeared);
+            mDisplayContent.updateImeParent();
+        }
     }
 
     @Override
@@ -4899,6 +4939,12 @@
             reconfigureDisplayLocked();
             onRequestedOverrideConfigurationChanged(getRequestedOverrideConfiguration());
             mWmService.mDisplayNotificationController.dispatchDisplayAdded(this);
+            // Attach the SystemUiContext to this DisplayContent the get latest configuration.
+            // Note that the SystemUiContext will be removed automatically if this DisplayContent
+            // is detached.
+            mWmService.mWindowContextListenerController.registerWindowContainerListener(
+                    getDisplayUiContext().getWindowContextToken(), this, SYSTEM_UID,
+                    INVALID_WINDOW_TYPE, null /* options */);
         }
     }
 
@@ -4909,6 +4955,15 @@
     }
 
     private void assignRelativeLayerForIme(SurfaceControl.Transaction t, boolean forceUpdate) {
+        if (mImeWindowsContainer.isOrganized()) {
+            if (DEBUG_INPUT_METHOD) {
+                Slog.i(TAG_WM, "ImeContainer is organized. Skip assignRelativeLayerForIme.");
+            }
+            // Leave the ImeContainer where the DisplayAreaPolicy placed it.
+            // When using FEATURE_IME, Organizer assumes the responsibility for placing the surface.
+            return;
+        }
+
         mImeWindowsContainer.setNeedsLayer();
         final WindowState imeTarget = mImeLayeringTarget;
         // In the case where we have an IME target that is not in split-screen mode IME
@@ -5424,29 +5479,44 @@
         return mMetricsLogger;
     }
 
+    void acquireScreenOffToken(boolean acquire) {
+        if (acquire) {
+            mOffTokenAcquirer.acquire(mDisplayId);
+        } else {
+            mOffTokenAcquirer.release(mDisplayId);
+        }
+    }
+
     void onDisplayChanged() {
         mDisplay.getRealSize(mTmpDisplaySize);
         setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
+        final int lastDisplayState = mDisplayInfo.state;
         updateDisplayInfo();
 
         // The window policy is responsible for stopping activities on the default display.
         final int displayId = mDisplay.getDisplayId();
+        final int displayState = mDisplayInfo.state;
         if (displayId != DEFAULT_DISPLAY) {
-            final int displayState = mDisplay.getState();
             if (displayState == Display.STATE_OFF) {
-                mOffTokenAcquirer.acquire(mDisplayId);
+                acquireScreenOffToken(true /* acquire */);
             } else if (displayState == Display.STATE_ON) {
-                mOffTokenAcquirer.release(mDisplayId);
+                acquireScreenOffToken(false /* acquire */);
             }
             ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
                     "Display %d state is now (%d), so update layer mirroring?",
                     mDisplayId, displayState);
-            if (mLastDisplayState != displayState) {
+            if (lastDisplayState != displayState) {
                 // If state is on due to surface being added, then start layer mirroring.
                 // If state is off due to surface being removed, then stop layer mirroring.
                 updateMirroring();
             }
-            mLastDisplayState = displayState;
+        }
+        // Dispatch pending Configuration to WindowContext if the associated display changes to
+        // un-suspended state from suspended.
+        if (isSuspendedState(lastDisplayState)
+                && !isSuspendedState(displayState) && displayState != STATE_UNKNOWN) {
+            mWmService.mWindowContextListenerController
+                    .dispatchPendingConfigurationIfNeeded(mDisplayId);
         }
         mWmService.requestTraversal();
     }
@@ -5841,6 +5911,30 @@
         return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0;
     }
 
+    /**
+     * @return whether keyguard is locked for this display
+     */
+    boolean isKeyguardLocked() {
+        return mRootWindowContainer.mTaskSupervisor
+                .getKeyguardController().isKeyguardLocked(mDisplayId);
+    }
+
+    /**
+     * @return whether keyguard is going away on this display
+     */
+    boolean isKeyguardGoingAway() {
+        return mRootWindowContainer.mTaskSupervisor
+                .getKeyguardController().isKeyguardGoingAway(mDisplayId);
+    }
+
+    /**
+     * @return whether AOD is showing on this display
+     */
+    boolean isAodShowing() {
+        return mRootWindowContainer.mTaskSupervisor
+                .getKeyguardController().isAodShowing(mDisplayId);
+    }
+
     @VisibleForTesting
     void removeAllTasks() {
         forAllTasks((t) -> { t.getRootTask().removeChild(t, "removeAllTasks"); });
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 2ea6334..cbb9d5d 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -302,6 +302,10 @@
     // needs to be opaque.
     private WindowState mNavBarBackgroundWindow;
 
+    // The window that draws fake rounded corners and should provide insets to calculate the correct
+    // rounded corner insets.
+    private WindowState mRoundedCornerWindow;
+
     /**
      * Windows to determine the color of status bar. See {@link #mNavBarColorWindowCandidate} for
      * the conditions of being candidate window.
@@ -422,7 +426,7 @@
                 : service.mContext.createDisplayContext(displayContent.getDisplay());
         mUiContext = displayContent.isDefaultDisplay ? service.mAtmService.mUiContext
                 : service.mAtmService.mSystemThread
-                        .createSystemUiContext(displayContent.getDisplayId());
+                        .getSystemUiContext(displayContent.getDisplayId());
         mDisplayContent = displayContent;
         mLock = service.getWindowManagerLock();
 
@@ -748,6 +752,10 @@
 
     public void setAwake(boolean awake) {
         mAwake = awake;
+        // The screen off token for non-default display is controlled by DisplayContent.
+        if (mDisplayContent.isDefaultDisplay) {
+            mDisplayContent.acquireScreenOffToken(!awake);
+        }
     }
 
     public boolean isAwake() {
@@ -927,6 +935,18 @@
             mExtraNavBarAltPosition = getAltBarPosition(attrs);
         }
 
+        if (attrs.insetsRoundedCornerFrame) {
+            // Currently, only support one rounded corner window which is the TaskBar.
+            if (mRoundedCornerWindow != null && mRoundedCornerWindow != win) {
+                throw new IllegalArgumentException("Found multiple rounded corner window :"
+                        + " current = " + mRoundedCornerWindow
+                        + " new = " + win);
+            }
+            mRoundedCornerWindow = win;
+        } else if (mRoundedCornerWindow == win) {
+            mRoundedCornerWindow = null;
+        }
+
         attrs.flags = sanitizeFlagSlippery(attrs.flags, attrs.privateFlags, win.getName());
     }
 
@@ -1250,6 +1270,10 @@
         if (mLastFocusedWindow == win) {
             mLastFocusedWindow = null;
         }
+        if (mRoundedCornerWindow == win) {
+            mRoundedCornerWindow = null;
+        }
+
         mInsetsSourceWindowsExceptIme.remove(win);
     }
 
@@ -1280,6 +1304,10 @@
         return mNavigationBar != null ? mNavigationBar : mNavigationBarAlt;
     }
 
+    WindowState getRoundedCornerWindow() {
+        return mRoundedCornerWindow;
+    }
+
     /**
      * Control the animation to run when a window's state changes.  Return a positive number to
      * force the animation to a specific resource ID, {@link #ANIMATION_STYLEABLE} to use the
@@ -1553,7 +1581,7 @@
         applyKeyguardPolicy(win, imeTarget);
 
         // Check if the freeform window overlaps with the navigation bar area.
-        final boolean isOverlappingWithNavBar = isOverlappingWithNavBar(win, mNavigationBar);
+        final boolean isOverlappingWithNavBar = isOverlappingWithNavBar(win);
         if (isOverlappingWithNavBar && !mIsFreeformWindowOverlappingWithNavBar
                 && win.inFreeformWindowingMode()) {
             mIsFreeformWindowOverlappingWithNavBar = true;
@@ -1714,7 +1742,7 @@
      * @param imeTarget The current IME target window.
      */
     private void applyKeyguardPolicy(WindowState win, WindowState imeTarget) {
-        if (mService.mPolicy.canBeHiddenByKeyguardLw(win)) {
+        if (win.canBeHiddenByKeyguard()) {
             if (shouldBeHiddenByKeyguard(win, imeTarget)) {
                 win.hide(false /* doAnimation */, true /* requestAnim */);
             } else {
@@ -1730,7 +1758,7 @@
         // drawing. This way, we know that the IME can be safely shown since the other windows are
         // now shown.
         final boolean hideIme = win.mIsImWindow
-                && (mService.mAtmService.mKeyguardController.isAodShowing()
+                && (mDisplayContent.isAodShowing()
                         || (mDisplayContent.isDefaultDisplay && !mWindowManagerDrawComplete));
         if (hideIme) {
             return true;
@@ -1743,7 +1771,7 @@
         // Show IME over the keyguard if the target allows it.
         final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisible()
                 && win.mIsImWindow && (imeTarget.canShowWhenLocked()
-                        || !mService.mPolicy.canBeHiddenByKeyguardLw(imeTarget));
+                        || !imeTarget.canBeHiddenByKeyguard());
         if (showImeOverKeyguard) {
             return false;
         }
@@ -1863,7 +1891,8 @@
         // user's package info (see ContextImpl.createDisplayContext)
         final LoadedApk pi = ActivityThread.currentActivityThread().getPackageInfo(
                 uiContext.getPackageName(), null, 0, userId);
-        mCurrentUserResources = ResourcesManager.getInstance().getResources(null,
+        mCurrentUserResources = ResourcesManager.getInstance().getResources(
+                uiContext.getWindowContextToken(),
                 pi.getResDir(),
                 null /* splitResDirs */,
                 pi.getOverlayDirs(),
@@ -2319,7 +2348,7 @@
     private int getStatusBarAppearance(WindowState opaque, WindowState opaqueOrDimming) {
         final boolean onKeyguard = isKeyguardShowing() && !isKeyguardOccluded();
         final WindowState colorWin = onKeyguard ? mNotificationShade : opaqueOrDimming;
-        return isLightBarAllowed(colorWin, ITYPE_STATUS_BAR) && (colorWin == opaque || onKeyguard)
+        return isLightBarAllowed(colorWin, Type.statusBars()) && (colorWin == opaque || onKeyguard)
                 ? (colorWin.mAttrs.insetsFlags.appearance & APPEARANCE_LIGHT_STATUS_BARS)
                 : 0;
     }
@@ -2367,7 +2396,7 @@
     @VisibleForTesting
     int updateLightNavigationBarLw(int appearance, WindowState navColorWin) {
         if (navColorWin == null || navColorWin.isDimming()
-                || !isLightBarAllowed(navColorWin, ITYPE_NAVIGATION_BAR)) {
+                || !isLightBarAllowed(navColorWin, Type.navigationBars())) {
             // Clear the light flag while not allowed.
             appearance &= ~APPEARANCE_LIGHT_NAVIGATION_BARS;
             return appearance;
@@ -2432,12 +2461,11 @@
         return appearance;
     }
 
-    private boolean isLightBarAllowed(WindowState win, @InternalInsetsType int type) {
+    private static boolean isLightBarAllowed(WindowState win, @InsetsType int type) {
         if (win == null) {
             return false;
         }
-        final InsetsSource source = win.getInsetsState().peekSource(type);
-        return source != null && Rect.intersects(win.getFrame(), source.getFrame());
+        return intersectsAnyInsets(win.getFrame(), win.getInsetsState(), type);
     }
 
     private Rect getBarContentFrameForWindow(WindowState win, @InternalInsetsType int type) {
@@ -2814,17 +2842,34 @@
     }
 
     @VisibleForTesting
-    static boolean isOverlappingWithNavBar(@NonNull WindowState targetWindow,
-            WindowState navBarWindow) {
-        if (navBarWindow == null || !navBarWindow.isVisible()
-                || targetWindow.mActivityRecord == null || !targetWindow.isVisible()) {
+    static boolean isOverlappingWithNavBar(@NonNull WindowState win) {
+        if (win.mActivityRecord == null || !win.isVisible()) {
             return false;
         }
 
         // When the window is dimming means it's requesting dim layer to its host container, so
-        // checking whether it's overlapping with navigation bar by its container's bounds.
-        return Rect.intersects(targetWindow.isDimming()
-                ? targetWindow.getBounds() : targetWindow.getFrame(), navBarWindow.getFrame());
+        // checking whether it's overlapping with a navigation bar by its container's bounds.
+        return intersectsAnyInsets(win.isDimming() ? win.getBounds() : win.getFrame(),
+                win.getInsetsState(), Type.navigationBars());
+    }
+
+    /**
+     * Returns whether the given {@param bounds} intersects with any insets of the
+     * provided {@param insetsType}.
+     */
+    private static boolean intersectsAnyInsets(Rect bounds, InsetsState insetsState,
+            @InsetsType int insetsType) {
+        final ArraySet<Integer> internalTypes = InsetsState.toInternalType(insetsType);
+        for (int i = 0; i < internalTypes.size(); i++) {
+            final InsetsSource source = insetsState.peekSource(internalTypes.valueAt(i));
+            if (source == null || !source.isVisible()) {
+                continue;
+            }
+            if (Rect.intersects(bounds, source.getFrame())) {
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index badb1f5..963f326 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -139,9 +139,6 @@
                 setActivityVisibilityState(child.asActivityRecord(), starting, resumeTopActivity);
             }
         }
-        if (mTaskFragment.mTransitionController.isShellTransitionsEnabled()) {
-            mTaskFragment.getDisplayContent().mWallpaperController.adjustWallpaperWindows();
-        }
     }
 
     private void setActivityVisibilityState(ActivityRecord r, ActivityRecord starting,
diff --git a/services/core/java/com/android/server/wm/EventLogTags.logtags b/services/core/java/com/android/server/wm/EventLogTags.logtags
index 40b80f7..e228a4b 100644
--- a/services/core/java/com/android/server/wm/EventLogTags.logtags
+++ b/services/core/java/com/android/server/wm/EventLogTags.logtags
@@ -52,7 +52,7 @@
 30066 wm_add_to_stopping (User|1|5),(Token|1|5),(Component Name|3),(Reason|3)
 
 # Keyguard status changed
-30067 wm_set_keyguard_shown (keyguardShowing|1),(aodShowing|1),(keyguardGoingAway|1),(Reason|3)
+30067 wm_set_keyguard_shown (Display Id|1|5),(keyguardShowing|1),(aodShowing|1),(keyguardGoingAway|1),(Reason|3)
 
 # Out of memory for surfaces.
 31000 wm_no_surface_memory (Window|3),(PID|1|5),(Operation|3)
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index d17c109..4225f21 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -50,7 +50,6 @@
 import static java.lang.Integer.MAX_VALUE;
 
 import android.annotation.Nullable;
-import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Handler;
 import android.os.IBinder;
@@ -262,9 +261,6 @@
                 && !mDisableWallpaperTouchEvents;
         inputWindowHandle.setHasWallpaper(hasWallpaper);
 
-        final Rect frame = w.getFrame();
-        inputWindowHandle.setFrame(frame.left, frame.top, frame.right, frame.bottom);
-
         // Surface insets are hardcoded to be the same in all directions
         // and we could probably deprecate the "left/right/top/bottom" concept.
         // we avoid reintroducing this concept by just choosing one of them here.
@@ -274,11 +270,19 @@
         // what is on screen to what is actually being touched in the UI.
         inputWindowHandle.setScaleFactor(w.mGlobalScale != 1f ? (1f / w.mGlobalScale) : 1f);
 
-        final int flags = w.getSurfaceTouchableRegion(mTmpRegion, w.mAttrs.flags);
-        inputWindowHandle.setTouchableRegion(mTmpRegion);
+        // Update layout params flags to force the window to be not touch modal. We do this to
+        // restrict the window's touchable region to the task even if it request touches outside its
+        // window bounds. An example is a dialog in primary split should get touches outside its
+        // window within the primary task but should not get any touches going to the secondary
+        // task.
+        int flags = w.mAttrs.flags;
+        if (w.mAttrs.isModal()) {
+            flags = flags | FLAG_NOT_TOUCH_MODAL;
+        }
         inputWindowHandle.setLayoutParamsFlags(flags);
 
-        boolean useSurfaceCrop = false;
+        boolean useSurfaceBoundsAsTouchRegion = false;
+        SurfaceControl touchableRegionCrop = null;
         final Task task = w.getTask();
         if (task != null) {
             // TODO(b/165794636): Remove the special case for freeform window once drag resizing is
@@ -290,20 +294,22 @@
                 // we need to make sure that these changes in crop are reflected in the input
                 // windows, and so ensure this flag is set so that the input crop always reflects
                 // the surface hierarchy.
-                // TODO(b/168252846): we have some issues with modal-windows, so we need to cross
-                // that bridge now that we organize full-screen Tasks.
-                inputWindowHandle.setTouchableRegionCrop(null /* Use this surfaces crop */);
-                inputWindowHandle.setReplaceTouchableRegionWithCrop(true);
-                useSurfaceCrop = true;
+                useSurfaceBoundsAsTouchRegion = true;
+
+                if (w.mAttrs.isModal()) {
+                    TaskFragment parent = w.getTaskFragment();
+                    touchableRegionCrop = parent != null ? parent.getSurfaceControl() : null;
+                }
             } else if (task.cropWindowsToRootTaskBounds() && !w.inFreeformWindowingMode()) {
-                inputWindowHandle.setTouchableRegionCrop(task.getRootTask().getSurfaceControl());
-                inputWindowHandle.setReplaceTouchableRegionWithCrop(false);
-                useSurfaceCrop = true;
+                touchableRegionCrop = task.getRootTask().getSurfaceControl();
             }
         }
-        if (!useSurfaceCrop) {
-            inputWindowHandle.setReplaceTouchableRegionWithCrop(false);
-            inputWindowHandle.setTouchableRegionCrop(null);
+        inputWindowHandle.setReplaceTouchableRegionWithCrop(useSurfaceBoundsAsTouchRegion);
+        inputWindowHandle.setTouchableRegionCrop(touchableRegionCrop);
+
+        if (!useSurfaceBoundsAsTouchRegion) {
+            w.getSurfaceTouchableRegion(mTmpRegion, w.mAttrs);
+            inputWindowHandle.setTouchableRegion(mTmpRegion);
         }
     }
 
@@ -497,12 +503,16 @@
 
             resetInputConsumers(mInputTransaction);
             // Update recents input consumer layer if active
-            if (mAddRecentsAnimationInputConsumerHandle
-                    && getWeak(mActiveRecentsActivity) != null) {
-                final WindowContainer layer = getWeak(mActiveRecentsLayerRef);
-                mRecentsAnimationInputConsumer.show(mInputTransaction,
-                        layer != null ? layer : getWeak(mActiveRecentsActivity));
-                mAddRecentsAnimationInputConsumerHandle = false;
+            final ActivityRecord activeRecents = getWeak(mActiveRecentsActivity);
+            if (mAddRecentsAnimationInputConsumerHandle && activeRecents != null
+                    && activeRecents.getSurfaceControl() != null) {
+                WindowContainer layer = getWeak(mActiveRecentsLayerRef);
+                layer = layer != null ? layer : activeRecents;
+                // Handle edge-case for SUW where windows don't exist yet
+                if (layer.getSurfaceControl() != null) {
+                    mRecentsAnimationInputConsumer.show(mInputTransaction, layer);
+                    mAddRecentsAnimationInputConsumerHandle = false;
+                }
             }
             mDisplayContent.forAllWindows(this, true /* traverseTopToBottom */);
             updateInputFocusRequest(mRecentsAnimationInputConsumer);
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 3d19f54..dff7ff9 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -33,6 +33,8 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.StatusBarManager;
+import android.graphics.Insets;
+import android.graphics.Rect;
 import android.util.IntArray;
 import android.util.SparseArray;
 import android.view.InsetsAnimationControlCallbacks;
@@ -50,7 +52,6 @@
 import android.view.WindowInsetsAnimation;
 import android.view.WindowInsetsAnimation.Bounds;
 import android.view.WindowInsetsAnimationControlListener;
-import android.view.WindowInsetsAnimationController;
 import android.view.WindowManager;
 
 import com.android.internal.R;
@@ -220,8 +221,9 @@
      */
     InsetsState getInsetsForWindow(WindowState target) {
         final InsetsState originalState = mStateController.getInsetsForWindow(target);
-        final InsetsState state = adjustVisibilityForTransientTypes(originalState);
-        return adjustVisibilityForIme(target, state, state == originalState);
+        InsetsState state = adjustVisibilityForTransientTypes(originalState);
+        state = adjustVisibilityForIme(target, state, state == originalState);
+        return adjustInsetsForRoundedCorners(target, state, state == originalState);
     }
 
     /**
@@ -286,6 +288,34 @@
         return originalState;
     }
 
+    private InsetsState adjustInsetsForRoundedCorners(WindowState w, InsetsState originalState,
+            boolean copyState) {
+        final WindowState roundedCornerWindow = mPolicy.getRoundedCornerWindow();
+        final Task task = w.getTask();
+        final boolean isInSplitScreenMode = task != null && task.inMultiWindowMode()
+                && task.getRootTask() != null
+                && task.getRootTask().getAdjacentTaskFragment() != null;
+        if (task != null && !task.getWindowConfiguration().tasksAreFloating()
+                && (roundedCornerWindow != null || isInSplitScreenMode)) {
+            // Instead of using display frame to calculating rounded corner, for the fake rounded
+            // corners drawn by divider bar or task bar, we need to re-calculate rounded corners
+            // based on task bounds and if the task bounds is intersected with task bar, we should
+            // exclude the intersected part.
+            final Rect roundedCornerFrame = new Rect(task.getBounds());
+            if (roundedCornerWindow != null
+                    && roundedCornerWindow.getControllableInsetProvider() != null) {
+                final InsetsSource source =
+                        roundedCornerWindow.getControllableInsetProvider().getSource();
+                final Insets insets = source.calculateInsets(roundedCornerFrame, false);
+                roundedCornerFrame.inset(insets);
+            }
+            final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
+            state.setRoundedCornerFrame(roundedCornerFrame);
+            return state;
+        }
+        return originalState;
+    }
+
     void onInsetsModified(InsetsControlTarget caller) {
         mStateController.onInsetsModified(caller);
         checkAbortTransient(caller);
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index bd41de3..a843909d 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -38,10 +38,8 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.wm.KeyguardControllerProto.AOD_SHOWING;
-import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES;
+import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_PER_DISPLAY;
 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_SHOWING;
-import static com.android.server.wm.KeyguardOccludedProto.DISPLAY_ID;
-import static com.android.server.wm.KeyguardOccludedProto.KEYGUARD_OCCLUDED;
 
 import android.annotation.Nullable;
 import android.os.IBinder;
@@ -73,21 +71,18 @@
 
     private final ActivityTaskSupervisor mTaskSupervisor;
     private WindowManagerService mWindowManager;
-    private boolean mKeyguardShowing;
-    private boolean mAodShowing;
-    private boolean mKeyguardGoingAway;
-    private boolean mDismissalRequested;
+
     private final SparseArray<KeyguardDisplayState> mDisplayStates = new SparseArray<>();
     private final ActivityTaskManagerService mService;
     private RootWindowContainer mRootWindowContainer;
-    private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
+    private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer;
 
 
     KeyguardController(ActivityTaskManagerService service,
             ActivityTaskSupervisor taskSupervisor) {
         mService = service;
         mTaskSupervisor = taskSupervisor;
-        mSleepTokenAcquirer = mService.new SleepTokenAcquirerImpl(KEYGUARD_SLEEP_TOKEN_TAG);
+        mSleepTokenAcquirer = mService.new SleepTokenAcquirer(KEYGUARD_SLEEP_TOKEN_TAG);
     }
 
     void setWindowManager(WindowManagerService windowManager) {
@@ -95,8 +90,8 @@
         mRootWindowContainer = mService.mRootWindowContainer;
     }
 
-    boolean isAodShowing() {
-        return mAodShowing;
+    boolean isAodShowing(int displayId) {
+        return getDisplayState(displayId).mAodShowing;
     }
 
     /**
@@ -104,7 +99,9 @@
      *         on the given display, false otherwise.
      */
     boolean isKeyguardOrAodShowing(int displayId) {
-        return (mKeyguardShowing || mAodShowing) && !mKeyguardGoingAway
+        final KeyguardDisplayState state = getDisplayState(displayId);
+        return (state.mKeyguardShowing || state.mAodShowing)
+                && !state.mKeyguardGoingAway
                 && !isDisplayOccluded(displayId);
     }
 
@@ -114,8 +111,9 @@
      * TODO(b/125198167): Replace isKeyguardOrAodShowing() by this logic.
      */
     boolean isKeyguardUnoccludedOrAodShowing(int displayId) {
-        if (displayId == DEFAULT_DISPLAY && mAodShowing) {
-            return !mKeyguardGoingAway;
+        final KeyguardDisplayState state = getDisplayState(displayId);
+        if (displayId == DEFAULT_DISPLAY && state.mAodShowing) {
+            return !state.mKeyguardGoingAway;
         }
         return isKeyguardOrAodShowing(displayId);
     }
@@ -125,14 +123,17 @@
      *         display, false otherwise
      */
     boolean isKeyguardShowing(int displayId) {
-        return mKeyguardShowing && !mKeyguardGoingAway && !isDisplayOccluded(displayId);
+        final KeyguardDisplayState state = getDisplayState(displayId);
+        return state.mKeyguardShowing && !state.mKeyguardGoingAway
+                && !isDisplayOccluded(displayId);
     }
 
     /**
      * @return true if Keyguard is either showing or occluded, but not going away
      */
-    boolean isKeyguardLocked() {
-        return mKeyguardShowing && !mKeyguardGoingAway;
+    boolean isKeyguardLocked(int displayId) {
+        final KeyguardDisplayState state = getDisplayState(displayId);
+        return state.mKeyguardShowing && !state.mKeyguardGoingAway;
     }
 
     /**
@@ -146,28 +147,31 @@
     /**
      * @return {@code true} if the keyguard is going away, {@code false} otherwise.
      */
-    boolean isKeyguardGoingAway() {
+    boolean isKeyguardGoingAway(int displayId) {
+        final KeyguardDisplayState state = getDisplayState(displayId);
         // Also check keyguard showing in case value is stale.
-        return mKeyguardGoingAway && mKeyguardShowing;
+        return state.mKeyguardGoingAway && state.mKeyguardShowing;
     }
 
     /**
      * Update the Keyguard showing state.
      */
-    void setKeyguardShown(boolean keyguardShowing, boolean aodShowing) {
-        final boolean aodChanged = aodShowing != mAodShowing;
+    void setKeyguardShown(int displayId, boolean keyguardShowing, boolean aodShowing) {
+        final KeyguardDisplayState state = getDisplayState(displayId);
+        final boolean aodChanged = aodShowing != state.mAodShowing;
         // If keyguard is going away, but SystemUI aborted the transition, need to reset state.
         // Do not reset keyguardChanged status if this is aodChanged.
-        final boolean keyguardChanged = (keyguardShowing != mKeyguardShowing)
-                || (mKeyguardGoingAway && keyguardShowing && !aodChanged);
+        final boolean keyguardChanged = (keyguardShowing != state.mKeyguardShowing)
+                || (state.mKeyguardGoingAway && keyguardShowing && !aodChanged);
         if (!keyguardChanged && !aodChanged) {
             setWakeTransitionReady();
             return;
         }
         EventLogTags.writeWmSetKeyguardShown(
+                displayId,
                 keyguardShowing ? 1 : 0,
                 aodShowing ? 1 : 0,
-                mKeyguardGoingAway ? 1 : 0,
+                state.mKeyguardGoingAway ? 1 : 0,
                 "setKeyguardShown");
 
         // Update the task snapshot if the screen will not be turned off. To make sure that the
@@ -180,13 +184,13 @@
         // - The display state is ON. Because if AOD is not on or pulsing, the display state will
         //   be OFF or DOZE (the path of screen off may have handled it).
         if (((aodShowing ^ keyguardShowing) || (aodShowing && aodChanged && keyguardChanged))
-                && !mKeyguardGoingAway && Display.isOnState(
+                && !state.mKeyguardGoingAway && Display.isOnState(
                         mRootWindowContainer.getDefaultDisplay().getDisplayInfo().state)) {
             mWindowManager.mTaskSnapshotController.snapshotForSleeping(DEFAULT_DISPLAY);
         }
 
-        mKeyguardShowing = keyguardShowing;
-        mAodShowing = aodShowing;
+        state.mKeyguardShowing = keyguardShowing;
+        state.mAodShowing = aodShowing;
         if (aodChanged) {
             // Ensure the new state takes effect.
             mWindowManager.mWindowPlacerLocked.performSurfacePlacement();
@@ -194,10 +198,11 @@
 
         if (keyguardChanged) {
             // Irrelevant to AOD.
-            dismissMultiWindowModeForTaskIfNeeded(null /* currentTaskControllsingOcclusion */);
-            mKeyguardGoingAway = false;
+            dismissMultiWindowModeForTaskIfNeeded(displayId,
+                    null /* currentTaskControllsingOcclusion */);
+            state.mKeyguardGoingAway = false;
             if (keyguardShowing) {
-                mDismissalRequested = false;
+                state.mDismissalRequested = false;
             }
         }
 
@@ -223,17 +228,19 @@
      * @param flags See {@link WindowManagerPolicy#KEYGUARD_GOING_AWAY_FLAG_TO_SHADE}
      *              etc.
      */
-    void keyguardGoingAway(int flags) {
-        if (!mKeyguardShowing) {
+    void keyguardGoingAway(int displayId, int flags) {
+        final KeyguardDisplayState state = getDisplayState(displayId);
+        if (!state.mKeyguardShowing) {
             return;
         }
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "keyguardGoingAway");
         mService.deferWindowLayout();
-        mKeyguardGoingAway = true;
+        state.mKeyguardGoingAway = true;
         try {
             EventLogTags.writeWmSetKeyguardShown(
+                    displayId,
                     1 /* keyguardShowing */,
-                    mAodShowing ? 1 : 0,
+                    state.mAodShowing ? 1 : 0,
                     1 /* keyguardGoingAway */,
                     "keyguardGoingAway");
             final int transitFlags = convertTransitFlags(flags);
@@ -307,10 +314,10 @@
         // Allow to show it when we are about to dismiss Keyguard. This isn't allowed if r is
         // already the dismissing activity, in which case we don't allow it to repeatedly dismiss
         // Keyguard.
-        return r.containsDismissKeyguardWindow() && canDismissKeyguard() && !mAodShowing
-                && (mDismissalRequested
-                || (r.canShowWhenLocked()
-                        && getDisplayState(r.getDisplayId()).mDismissingKeyguardActivity != r));
+        final KeyguardDisplayState state = getDisplayState(r.getDisplayId());
+        return r.containsDismissKeyguardWindow() && canDismissKeyguard() && !state.mAodShowing
+                && (state.mDismissalRequested
+                || (r.canShowWhenLocked() && state.mDismissingKeyguardActivity != r));
     }
 
     /**
@@ -335,7 +342,7 @@
             // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard
             // right away and AOD isn't visible.
             return canShowActivityWhileKeyguardShowing(r);
-        } else if (isKeyguardLocked()) {
+        } else if (isKeyguardLocked(r.getDisplayId())) {
             return canShowWhileOccluded(r.containsDismissKeyguardWindow(), r.canShowWhenLocked());
         } else {
             return true;
@@ -348,19 +355,15 @@
      * ({@link ActivityTaskSupervisor#beginActivityVisibilityUpdate}).
      */
     void updateVisibility() {
-        boolean requestDismissKeyguard = false;
         for (int displayNdx = mRootWindowContainer.getChildCount() - 1;
              displayNdx >= 0; displayNdx--) {
             final DisplayContent display = mRootWindowContainer.getChildAt(displayNdx);
             if (display.isRemoving() || display.isRemoved()) continue;
             final KeyguardDisplayState state = getDisplayState(display.mDisplayId);
             state.updateVisibility(this, display);
-            requestDismissKeyguard |= state.mRequestDismissKeyguard;
-        }
-
-        // Dismissing Keyguard happens globally using the information from all displays.
-        if (requestDismissKeyguard) {
-            handleDismissKeyguard();
+            if (state.mRequestDismissKeyguard) {
+                handleDismissKeyguard(display.getDisplayId());
+            }
         }
     }
 
@@ -381,7 +384,7 @@
         }
 
         mWindowManager.mPolicy.onKeyguardOccludedChangedLw(isDisplayOccluded(DEFAULT_DISPLAY));
-        if (isKeyguardLocked()) {
+        if (isKeyguardLocked(displayId)) {
             mService.deferWindowLayout();
             try {
                 mRootWindowContainer.getDefaultDisplay()
@@ -395,14 +398,14 @@
                 mService.continueWindowLayout();
             }
         }
-        dismissMultiWindowModeForTaskIfNeeded(topActivity != null
+        dismissMultiWindowModeForTaskIfNeeded(displayId, topActivity != null
                 ? topActivity.getRootTask() : null);
     }
 
     /**
      * Called when somebody wants to dismiss the Keyguard via the flag.
      */
-    private void handleDismissKeyguard() {
+    private void handleDismissKeyguard(int displayId) {
         // We only allow dismissing Keyguard via the flag when Keyguard is secure for legacy
         // reasons, because that's how apps used to dismiss Keyguard in the secure case. In the
         // insecure case, we actually show it on top of the lockscreen. See #canShowWhileOccluded.
@@ -411,12 +414,13 @@
         }
 
         mWindowManager.dismissKeyguard(null /* callback */, null /* message */);
-        mDismissalRequested = true;
+        final KeyguardDisplayState state = getDisplayState(displayId);
+        state.mDismissalRequested = true;
 
         // If we are about to unocclude the Keyguard, but we can dismiss it without security,
         // we immediately dismiss the Keyguard so the activity gets shown without a flicker.
         final DisplayContent dc = mRootWindowContainer.getDefaultDisplay();
-        if (mKeyguardShowing && canDismissKeyguard()
+        if (state.mKeyguardShowing && canDismissKeyguard()
                 && dc.mAppTransition.containsTransitRequest(TRANSIT_KEYGUARD_UNOCCLUDE)) {
             mWindowManager.executeAppTransition();
         }
@@ -434,10 +438,10 @@
                 || !mWindowManager.isKeyguardSecure(mService.getCurrentUserId());
     }
 
-    private void dismissMultiWindowModeForTaskIfNeeded(
+    private void dismissMultiWindowModeForTaskIfNeeded(int displayId,
             @Nullable Task currentTaskControllingOcclusion) {
         // TODO(b/113840485): Handle docked stack for individual display.
-        if (!mKeyguardShowing || !isDisplayOccluded(DEFAULT_DISPLAY)) {
+        if (!getDisplayState(displayId).mKeyguardShowing || !isDisplayOccluded(DEFAULT_DISPLAY)) {
             return;
         }
 
@@ -497,6 +501,10 @@
     /** Represents Keyguard state per individual display. */
     private static class KeyguardDisplayState {
         private final int mDisplayId;
+        private boolean mKeyguardShowing;
+        private boolean mAodShowing;
+        private boolean mKeyguardGoingAway;
+        private boolean mDismissalRequested;
         private boolean mOccluded;
 
         private ActivityRecord mTopOccludesActivity;
@@ -505,10 +513,10 @@
 
         private boolean mRequestDismissKeyguard;
         private final ActivityTaskManagerService mService;
-        private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
+        private final ActivityTaskManagerService.SleepTokenAcquirer mSleepTokenAcquirer;
 
         KeyguardDisplayState(ActivityTaskManagerService service, int displayId,
-                ActivityTaskManagerInternal.SleepTokenAcquirer acquirer) {
+                ActivityTaskManagerService.SleepTokenAcquirer acquirer) {
             mService = service;
             mDisplayId = displayId;
             mSleepTokenAcquirer = acquirer;
@@ -604,7 +612,16 @@
         void dumpStatus(PrintWriter pw, String prefix) {
             final StringBuilder sb = new StringBuilder();
             sb.append(prefix);
-            sb.append("  Occluded=").append(mOccluded)
+            sb.append(" KeyguardShowing=")
+                    .append(mKeyguardShowing)
+                    .append(" AodShowing=")
+                    .append(mAodShowing)
+                    .append(" KeyguardGoingAway=")
+                    .append(mKeyguardGoingAway)
+                    .append(" DismissalRequested=")
+                    .append(mDismissalRequested)
+                    .append("  Occluded=")
+                    .append(mOccluded)
                     .append(" DismissingKeyguardActivity=")
                     .append(mDismissingKeyguardActivity)
                     .append(" TurnScreenOnActivity=")
@@ -616,27 +633,31 @@
 
         void dumpDebug(ProtoOutputStream proto, long fieldId) {
             final long token = proto.start(fieldId);
-            proto.write(DISPLAY_ID, mDisplayId);
-            proto.write(KEYGUARD_OCCLUDED, mOccluded);
+            proto.write(KeyguardPerDisplayProto.DISPLAY_ID, mDisplayId);
+            proto.write(KeyguardPerDisplayProto.KEYGUARD_SHOWING, mKeyguardShowing);
+            proto.write(KeyguardPerDisplayProto.AOD_SHOWING, mAodShowing);
+            proto.write(KeyguardPerDisplayProto.KEYGUARD_OCCLUDED, mOccluded);
             proto.end(token);
         }
     }
 
     void dump(PrintWriter pw, String prefix) {
+        final KeyguardDisplayState default_state = getDisplayState(DEFAULT_DISPLAY);
         pw.println(prefix + "KeyguardController:");
-        pw.println(prefix + "  mKeyguardShowing=" + mKeyguardShowing);
-        pw.println(prefix + "  mAodShowing=" + mAodShowing);
-        pw.println(prefix + "  mKeyguardGoingAway=" + mKeyguardGoingAway);
+        pw.println(prefix + "  mKeyguardShowing=" + default_state.mKeyguardShowing);
+        pw.println(prefix + "  mAodShowing=" + default_state.mAodShowing);
+        pw.println(prefix + "  mKeyguardGoingAway=" + default_state.mKeyguardGoingAway);
         dumpDisplayStates(pw, prefix);
-        pw.println(prefix + "  mDismissalRequested=" + mDismissalRequested);
+        pw.println(prefix + "  mDismissalRequested=" + default_state.mDismissalRequested);
         pw.println();
     }
 
     void dumpDebug(ProtoOutputStream proto, long fieldId) {
+        final KeyguardDisplayState default_state = getDisplayState(DEFAULT_DISPLAY);
         final long token = proto.start(fieldId);
-        proto.write(AOD_SHOWING, mAodShowing);
-        proto.write(KEYGUARD_SHOWING, mKeyguardShowing);
-        writeDisplayStatesToProto(proto, KEYGUARD_OCCLUDED_STATES);
+        proto.write(AOD_SHOWING, default_state.mAodShowing);
+        proto.write(KEYGUARD_SHOWING, default_state.mKeyguardShowing);
+        writeDisplayStatesToProto(proto, KEYGUARD_PER_DISPLAY);
         proto.end(token);
     }
 
diff --git a/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java b/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java
index 9f28509..49d30cd 100644
--- a/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/NonAppWindowAnimationAdapter.java
@@ -69,25 +69,32 @@
             long durationHint, long statusBarTransitionDelay,
             ArrayList<NonAppWindowAnimationAdapter> adaptersOut) {
         final ArrayList<RemoteAnimationTarget> targets = new ArrayList<>();
-        if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
-                || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER) {
+        if (shouldStartNonAppWindowAnimationsForKeyguardExit(transit)) {
             startNonAppWindowAnimationsForKeyguardExit(
                     service, durationHint, statusBarTransitionDelay, targets, adaptersOut);
-        } else if (transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT
-                || transit == TRANSIT_OLD_WALLPAPER_CLOSE) {
-            final boolean shouldAttachNavBarToApp =
-                    displayContent.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition()
-                            && service.getRecentsAnimationController() == null
-                            && displayContent.getFadeRotationAnimationController() == null;
-            if (shouldAttachNavBarToApp) {
-                startNavigationBarWindowAnimation(
-                        displayContent, durationHint, statusBarTransitionDelay, targets,
-                        adaptersOut);
-            }
+        } else if (shouldAttachNavBarToApp(service, displayContent, transit)) {
+            startNavigationBarWindowAnimation(
+                    displayContent, durationHint, statusBarTransitionDelay, targets,
+                    adaptersOut);
         }
         return targets.toArray(new RemoteAnimationTarget[targets.size()]);
     }
 
+    static boolean shouldStartNonAppWindowAnimationsForKeyguardExit(
+            @WindowManager.TransitionOldType int transit) {
+        return transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY
+                || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
+    }
+
+    static boolean shouldAttachNavBarToApp(WindowManagerService service,
+            DisplayContent displayContent, @WindowManager.TransitionOldType int transit) {
+        return (transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT
+                || transit == TRANSIT_OLD_WALLPAPER_CLOSE)
+                && displayContent.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition()
+                && service.getRecentsAnimationController() == null
+                && displayContent.getFadeRotationAnimationController() == null;
+    }
+
     /**
      * Creates and starts remote animations for all the visible non app windows.
      *
@@ -101,7 +108,7 @@
         final WindowManagerPolicy policy = service.mPolicy;
         service.mRoot.forAllWindows(nonAppWindow -> {
             // Animation on the IME window is controlled via Insets.
-            if (nonAppWindow.mActivityRecord == null && policy.canBeHiddenByKeyguardLw(nonAppWindow)
+            if (nonAppWindow.mActivityRecord == null && nonAppWindow.canBeHiddenByKeyguard()
                     && nonAppWindow.wouldBeVisibleIfPolicyIgnored() && !nonAppWindow.isVisible()
                     && nonAppWindow != service.mRoot.getCurrentInputMethodWindow()) {
                 final NonAppWindowAnimationAdapter nonAppAdapter = new NonAppWindowAnimationAdapter(
diff --git a/services/core/java/com/android/server/wm/PackageConfigPersister.java b/services/core/java/com/android/server/wm/PackageConfigPersister.java
index 3de98f1..7a7fb65 100644
--- a/services/core/java/com/android/server/wm/PackageConfigPersister.java
+++ b/services/core/java/com/android/server/wm/PackageConfigPersister.java
@@ -169,21 +169,35 @@
         }
     }
 
+    /**
+     * Returns true when the app specific configuration is successfully stored or removed based on
+     * the current requested configuration. It will return false when the requested
+     * configuration is same as the pre-existing app-specific configuration.
+     */
     @GuardedBy("mLock")
     boolean updateFromImpl(String packageName, int userId,
             PackageConfigurationUpdaterImpl impl) {
         synchronized (mLock) {
-            PackageConfigRecord record = findRecordOrCreate(mModified, packageName, userId);
-            if (impl.getNightMode() != null) {
-                record.mNightMode = impl.getNightMode();
+            boolean isRecordPresent = false;
+            PackageConfigRecord record = findRecord(mModified, packageName, userId);
+            if (record != null) {
+                isRecordPresent = true;
+            } else {
+                record = findRecordOrCreate(mModified, packageName, userId);
             }
-            if (impl.getLocales() != null) {
-                record.mLocales = impl.getLocales();
-            }
+            boolean isNightModeChanged = updateNightMode(impl.getNightMode(), record);
+            boolean isLocalesChanged = updateLocales(impl.getLocales(), record);
+
             if ((record.mNightMode == null || record.isResetNightMode())
                     && (record.mLocales == null || record.mLocales.isEmpty())) {
                 // if all values default to system settings, we can remove the package.
                 removePackage(packageName, userId);
+                // if there was a pre-existing record for the package that was deleted,
+                // we return true (since it was successfully deleted), else false (since there was
+                // no change to the previous state).
+                return isRecordPresent;
+            } else if (!isNightModeChanged && !isLocalesChanged) {
+                return false;
             } else {
                 final PackageConfigRecord pendingRecord =
                         findRecord(mPendingWrite, record.mName, record.mUserId);
@@ -195,7 +209,8 @@
                     writeRecord = pendingRecord;
                 }
 
-                if (!updateNightMode(record, writeRecord) && !updateLocales(record, writeRecord)) {
+                if (!updateNightMode(record.mNightMode, writeRecord)
+                        && !updateLocales(record.mLocales, writeRecord)) {
                     return false;
                 }
 
@@ -203,24 +218,24 @@
                     Slog.d(TAG, "PackageConfigUpdater save config " + writeRecord);
                 }
                 mPersisterQueue.addItem(new WriteProcessItem(writeRecord), false /* flush */);
+                return true;
             }
-            return true;
         }
     }
 
-    private boolean updateNightMode(PackageConfigRecord record, PackageConfigRecord writeRecord) {
-        if (record.mNightMode == null || record.mNightMode.equals(writeRecord.mNightMode)) {
+    private boolean updateNightMode(Integer requestedNightMode, PackageConfigRecord record) {
+        if (requestedNightMode == null || requestedNightMode.equals(record.mNightMode)) {
             return false;
         }
-        writeRecord.mNightMode = record.mNightMode;
+        record.mNightMode = requestedNightMode;
         return true;
     }
 
-    private boolean updateLocales(PackageConfigRecord record, PackageConfigRecord writeRecord) {
-        if (record.mLocales == null || record.mLocales.equals(writeRecord.mLocales)) {
+    private boolean updateLocales(LocaleList requestedLocaleList, PackageConfigRecord record) {
+        if (requestedLocaleList == null || requestedLocaleList.equals(record.mLocales)) {
             return false;
         }
-        writeRecord.mLocales = record.mLocales;
+        record.mLocales = requestedLocaleList;
         return true;
     }
 
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index c28d089..117b22a 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -225,7 +225,7 @@
     private static final String DISPLAY_OFF_SLEEP_TOKEN_TAG = "Display-off";
 
     /** The token acquirer to put root tasks on the displays to sleep */
-    final ActivityTaskManagerInternal.SleepTokenAcquirer mDisplayOffTokenAcquirer;
+    final ActivityTaskManagerService.SleepTokenAcquirer mDisplayOffTokenAcquirer;
 
     /**
      * The modes which affect which tasks are returned when calling
@@ -470,7 +470,7 @@
         mService = service.mAtmService;
         mTaskSupervisor = mService.mTaskSupervisor;
         mTaskSupervisor.mRootWindowContainer = this;
-        mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirerImpl(DISPLAY_OFF_SLEEP_TOKEN_TAG);
+        mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirer(DISPLAY_OFF_SLEEP_TOKEN_TAG);
     }
 
     boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
@@ -2496,7 +2496,7 @@
             // starts. Instead, we expect home activities to be launched when the system is ready
             // (ActivityManagerService#systemReady).
             if (mService.isBooted() || mService.isBooting()) {
-                startSystemDecorations(display.mDisplayContent);
+                startSystemDecorations(display);
             }
             // Drop any cached DisplayInfos associated with this display id - the values are now
             // out of date given this display added event.
@@ -3480,7 +3480,9 @@
         // avoid power mode from being cleared before that, add a special reason to consider whether
         // the unknown visibility is resolved. The case from SystemUI is excluded because it should
         // rely on keyguard-going-away.
-        if (mService.mKeyguardController.isKeyguardLocked() && targetActivity != null
+        final boolean isKeyguardLocked = (targetActivity != null)
+                ? targetActivity.isKeyguardLocked() : mDefaultDisplay.isKeyguardLocked();
+        if (isKeyguardLocked && targetActivity != null
                 && !targetActivity.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_SYSTEMUI)) {
             final ActivityOptions opts = targetActivity.getOptions();
             if (opts == null || opts.getSourceInfo() == null
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 35d93f6..5af1c8e 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -2152,10 +2152,7 @@
     }
 
     private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
-        if (mWmService.mDisableTransitionAnimation
-                || !isVisible()
-                || getSurfaceControl() == null
-                || !isLeafTask()) {
+        if (!isLeafTask() || !canStartChangeTransition()) {
             return false;
         }
         // Only do an animation into and out-of freeform mode for now. Other mode
@@ -6080,11 +6077,13 @@
 
     boolean shouldSleepActivities() {
         final DisplayContent display = mDisplayContent;
+        final boolean isKeyguardGoingAway = (mDisplayContent != null)
+                ? mDisplayContent.isKeyguardGoingAway()
+                : mRootWindowContainer.getDefaultDisplay().isKeyguardGoingAway();
 
         // Do not sleep activities in this root task if we're marked as focused and the keyguard
         // is in the process of going away.
-        if (mTaskSupervisor.getKeyguardController().isKeyguardGoingAway()
-                && isFocusedRootTaskOnDisplay()
+        if (isKeyguardGoingAway && isFocusedRootTaskOnDisplay()
                 // Avoid resuming activities on secondary displays since we don't want bubble
                 // activities to be resumed while bubble is still collapsed.
                 // TODO(b/113840485): Having keyguard going away state for secondary displays.
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 3387e37..796a90a 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -808,6 +808,10 @@
         // Place root home tasks to the bottom.
         layer = adjustRootTaskLayer(t, mTmpHomeChildren, layer);
         layer = adjustRootTaskLayer(t, mTmpNormalChildren, layer);
+        // TODO(b/207185041): Remove this divider workaround after we full remove leagacy split and
+        //                    make app pair split only have single root then we can just attach the
+        //                    divider to the single root task in shell.
+        layer = Math.max(layer, SPLIT_DIVIDER_LAYER + 1);
         adjustRootTaskLayer(t, mTmpAlwaysOnTopChildren, layer);
         t.setLayer(mSplitScreenDividerAnchor, SPLIT_DIVIDER_LAYER);
     }
@@ -905,18 +909,24 @@
         mBackgroundColor = colorInt;
         Color color = Color.valueOf(colorInt);
         mColorLayerCounter++;
-        getPendingTransaction()
-                .setColor(mSurfaceControl, new float[]{color.red(), color.green(), color.blue()});
 
-        scheduleAnimation();
+        // Only apply the background color if the TDA is actually attached and has a valid surface
+        // to set the background color on. We still want to keep track of the background color state
+        // even if we are not showing it for when/if the TDA is reattached and gets a valid surface
+        if (mSurfaceControl != null) {
+            getPendingTransaction()
+                    .setColor(mSurfaceControl,
+                            new float[]{color.red(), color.green(), color.blue()});
+            scheduleAnimation();
+        }
     }
 
     void clearBackgroundColor() {
         mColorLayerCounter--;
 
         // Only clear the color layer if we have received the same amounts of clear as set
-        // requests.
-        if (mColorLayerCounter == 0) {
+        // requests and TDA has a non null surface control (i.e. is attached)
+        if (mColorLayerCounter == 0 && mSurfaceControl != null) {
             getPendingTransaction().unsetColor(mSurfaceControl);
             scheduleAnimation();
         }
@@ -1728,7 +1738,7 @@
         // the locked state, the keyguard isn't locked, or we can show when locked.
         if (topRunning != null && considerKeyguardState
                 && mRootWindowContainer.mTaskSupervisor.getKeyguardController()
-                .isKeyguardLocked()
+                .isKeyguardLocked(topRunning.getDisplayId())
                 && !topRunning.canShowWhenLocked()) {
             return null;
         }
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 0eaa25b..e497b53 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1413,29 +1413,29 @@
 
         boolean pauseImmediately = false;
         boolean shouldAutoPip = false;
-        if (resuming != null && (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0) {
-            // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
-            // activity to be paused, while at the same time resuming the new resume activity
-            // only if the previous activity can't go into Pip since we want to give Pip
-            // activities a chance to enter Pip before resuming the next activity.
-            final boolean lastResumedCanPip = prev != null && prev.checkEnterPictureInPictureState(
-                    "shouldResumeWhilePausing", userLeaving);
+        if (resuming != null) {
+            // Resuming the new resume activity only if the previous activity can't go into Pip
+            // since we want to give Pip activities a chance to enter Pip before resuming the
+            // next activity.
+            final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState(
+                    "shouldAutoPipWhilePausing", userLeaving);
             if (lastResumedCanPip && prev.pictureInPictureArgs.isAutoEnterEnabled()) {
                 shouldAutoPip = true;
             } else if (!lastResumedCanPip) {
-                pauseImmediately = true;
+                // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
+                // activity to be paused.
+                pauseImmediately = (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
             } else {
                 // The previous activity may still enter PIP even though it did not allow auto-PIP.
             }
         }
 
-        boolean didAutoPip = false;
         if (prev.attachedToProcess()) {
             if (shouldAutoPip) {
+                boolean didAutoPip = mAtmService.enterPictureInPictureMode(
+                        prev, prev.pictureInPictureArgs);
                 ProtoLog.d(WM_DEBUG_STATES, "Auto-PIP allowed, entering PIP mode "
-                        + "directly: %s", prev);
-
-                didAutoPip = mAtmService.enterPictureInPictureMode(prev, prev.pictureInPictureArgs);
+                        + "directly: %s, didAutoPip: %b", prev, didAutoPip);
             } else {
                 schedulePauseActivity(prev, userLeaving, pauseImmediately, reason);
             }
@@ -2121,13 +2121,7 @@
 
     /** Whether we should prepare a transition for this {@link TaskFragment} bounds change. */
     private boolean shouldStartChangeTransition(Rect startBounds) {
-        if (mWmService.mDisableTransitionAnimation
-                || mDisplayContent == null
-                || mTaskFragmentOrganizer == null
-                || getSurfaceControl() == null
-                // The change transition will be covered by display.
-                || mDisplayContent.inTransition()
-                || !isVisible()) {
+        if (mTaskFragmentOrganizer == null || !canStartChangeTransition()) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
index d911656..29c27f9 100644
--- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java
@@ -31,10 +31,8 @@
 import android.util.ArrayMap;
 import android.util.Slog;
 import android.view.RemoteAnimationDefinition;
-import android.view.SurfaceControl;
 import android.window.ITaskFragmentOrganizer;
 import android.window.ITaskFragmentOrganizerController;
-import android.window.TaskFragmentAppearedInfo;
 import android.window.TaskFragmentInfo;
 
 import com.android.internal.protolog.common.ProtoLog;
@@ -135,11 +133,8 @@
         void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment tf) {
             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName());
             final TaskFragmentInfo info = tf.getTaskFragmentInfo();
-            final SurfaceControl outSurfaceControl = new SurfaceControl(tf.getSurfaceControl(),
-                    "TaskFragmentOrganizerController.onTaskFragmentInfoAppeared");
             try {
-                organizer.onTaskFragmentAppeared(
-                        new TaskFragmentAppearedInfo(info, outSurfaceControl));
+                organizer.onTaskFragmentAppeared(info);
                 mLastSentTaskFragmentInfos.put(tf, info);
                 tf.mTaskFragmentAppearedSent = true;
             } catch (RemoteException e) {
@@ -434,6 +429,9 @@
         private final TaskFragment mTaskFragment;
         private final IBinder mErrorCallback;
         private final Throwable mException;
+        // Set when the event is deferred due to the host task is invisible. The defer time will
+        // be the last active time of the host task.
+        private long mDeferTime;
 
         private PendingTaskFragmentEvent(TaskFragment taskFragment,
                 ITaskFragmentOrganizer taskFragmentOrg, @EventType int eventType) {
@@ -503,11 +501,45 @@
                 || mPendingTaskFragmentEvents.isEmpty()) {
             return;
         }
+
+        final ArrayList<Task> visibleTasks = new ArrayList<>();
+        final ArrayList<Task> invisibleTasks = new ArrayList<>();
+        final ArrayList<PendingTaskFragmentEvent> candidateEvents = new ArrayList<>();
         for (int i = 0, n = mPendingTaskFragmentEvents.size(); i < n; i++) {
-            PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
-            dispatchEvent(event);
+            final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
+            final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null;
+            if (task != null && (task.lastActiveTime <= event.mDeferTime
+                    || !isTaskVisible(task, visibleTasks, invisibleTasks))) {
+                // Defer sending events to the TaskFragment until the host task is active again.
+                event.mDeferTime = task.lastActiveTime;
+                continue;
+            }
+            candidateEvents.add(event);
         }
-        mPendingTaskFragmentEvents.clear();
+        final int numEvents = candidateEvents.size();
+        for (int i = 0; i < numEvents; i++) {
+            dispatchEvent(candidateEvents.get(i));
+        }
+        if (numEvents > 0) {
+            mPendingTaskFragmentEvents.removeAll(candidateEvents);
+        }
+    }
+
+    private static boolean isTaskVisible(Task task, ArrayList<Task> knownVisibleTasks,
+            ArrayList<Task> knownInvisibleTasks) {
+        if (knownVisibleTasks.contains(task)) {
+            return true;
+        }
+        if (knownInvisibleTasks.contains(task)) {
+            return false;
+        }
+        if (task.shouldBeVisible(null /* starting */)) {
+            knownVisibleTasks.add(task);
+            return true;
+        } else {
+            knownInvisibleTasks.add(task);
+            return false;
+        }
     }
 
     void dispatchPendingInfoChangedEvent(TaskFragment taskFragment) {
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 4db8ef4..7349594 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -244,11 +244,11 @@
         }
         mParticipants.add(wc);
         if (info.mShowWallpaper) {
-            // Collect the wallpaper so it is part of the sync set.
-            final WindowContainer wallpaper =
+            // Collect the wallpaper token (for isWallpaper(wc)) so it is part of the sync set.
+            final WindowState wallpaper =
                     wc.getDisplayContent().mWallpaperController.getTopVisibleWallpaper();
             if (wallpaper != null) {
-                collect(wallpaper);
+                collect(wallpaper.mToken);
             }
         }
     }
@@ -495,25 +495,35 @@
             Slog.e(TAG, "Unexpected Sync ID " + syncId + ". Expected " + mSyncId);
             return;
         }
-        int displayId = DEFAULT_DISPLAY;
-        for (WindowContainer container : mParticipants) {
-            if (container.mDisplayContent == null) continue;
-            displayId = container.mDisplayContent.getDisplayId();
+        boolean hasWallpaper = false;
+        DisplayContent dc = null;
+        for (int i = mParticipants.size() - 1; i >= 0; --i) {
+            final WindowContainer<?> wc = mParticipants.valueAt(i);
+            if (dc == null && wc.mDisplayContent != null) {
+                dc = wc.mDisplayContent;
+            }
+            if (!hasWallpaper && isWallpaper(wc)) {
+                hasWallpaper = true;
+            }
         }
+        if (dc == null) dc = mController.mAtm.mRootWindowContainer.getDefaultDisplay();
 
         if (mState == STATE_ABORT) {
             mController.abort(this);
-            mController.mAtm.mRootWindowContainer.getDisplayContent(displayId)
-                    .getPendingTransaction().merge(transaction);
+            dc.getPendingTransaction().merge(transaction);
             mSyncId = -1;
             mOverrideOptions = null;
             return;
         }
+        // Ensure that wallpaper visibility is updated with the latest wallpaper target.
+        if (hasWallpaper) {
+            dc.mWallpaperController.adjustWallpaperWindows();
+        }
 
         mState = STATE_PLAYING;
         mController.moveToPlaying(this);
 
-        if (mController.mAtm.mTaskSupervisor.getKeyguardController().isKeyguardLocked()) {
+        if (dc.isKeyguardLocked()) {
             mFlags |= TRANSIT_FLAG_KEYGUARD_LOCKED;
         }
 
@@ -523,9 +533,9 @@
         info.setAnimationOptions(mOverrideOptions);
 
         // TODO(b/188669821): Move to animation impl in shell.
-        handleLegacyRecentsStartBehavior(displayId, info);
+        handleLegacyRecentsStartBehavior(dc, info);
 
-        handleNonAppWindowsInTransition(displayId, mType, mFlags);
+        handleNonAppWindowsInTransition(dc, mType, mFlags);
 
         reportStartReasonsToLogger();
 
@@ -627,14 +637,11 @@
     }
 
     /** @see RecentsAnimationController#attachNavigationBarToApp */
-    private void handleLegacyRecentsStartBehavior(int displayId, TransitionInfo info) {
+    private void handleLegacyRecentsStartBehavior(DisplayContent dc, TransitionInfo info) {
         if ((mFlags & TRANSIT_FLAG_IS_RECENTS) == 0) {
             return;
         }
-        final DisplayContent dc =
-                mController.mAtm.mRootWindowContainer.getDisplayContent(displayId);
-        if (dc == null) return;
-        mRecentsDisplayId = displayId;
+        mRecentsDisplayId = dc.mDisplayId;
 
         // Recents has an input-consumer to grab input from the "live tile" app. Set that up here
         final InputConsumerImpl recentsAnimationInputConsumer =
@@ -679,7 +686,7 @@
         // Find the top-most non-home, closing app.
         for (int i = 0; i < info.getChanges().size(); ++i) {
             final TransitionInfo.Change c = info.getChanges().get(i);
-            if (c.getTaskInfo() == null || c.getTaskInfo().displayId != displayId
+            if (c.getTaskInfo() == null || c.getTaskInfo().displayId != mRecentsDisplayId
                     || c.getTaskInfo().getActivityType() != ACTIVITY_TYPE_STANDARD
                     || !(c.getMode() == TRANSIT_CLOSE || c.getMode() == TRANSIT_TO_BACK)) {
                 continue;
@@ -710,7 +717,7 @@
             t.setLayer(navSurfaceControl, Integer.MAX_VALUE);
         }
         if (mController.mStatusBar != null) {
-            mController.mStatusBar.setNavigationBarLumaSamplingEnabled(displayId, false);
+            mController.mStatusBar.setNavigationBarLumaSamplingEnabled(mRecentsDisplayId, false);
         }
     }
 
@@ -760,13 +767,8 @@
         }
     }
 
-    private void handleNonAppWindowsInTransition(int displayId,
+    private void handleNonAppWindowsInTransition(@NonNull DisplayContent dc,
             @TransitionType int transit, @TransitionFlags int flags) {
-        final DisplayContent dc =
-                mController.mAtm.mRootWindowContainer.getDisplayContent(displayId);
-        if (dc == null) {
-            return;
-        }
         if ((transit == TRANSIT_KEYGUARD_GOING_AWAY
                 || (flags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0)
                 && !WindowManagerService.sEnableRemoteKeyguardGoingAwayAnimation) {
diff --git a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
index 2652723..4a5a20e 100644
--- a/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/WallpaperAnimationAdapter.java
@@ -69,7 +69,7 @@
             long durationHint, long statusBarTransitionDelay,
             Consumer<WallpaperAnimationAdapter> animationCanceledRunnable,
             ArrayList<WallpaperAnimationAdapter> adaptersOut) {
-        if (!displayContent.mWallpaperController.isWallpaperVisible()) {
+        if (!shouldStartWallpaperAnimation(displayContent)) {
             ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS,
                     "\tWallpaper of display=%s is not visible", displayContent);
             return new RemoteAnimationTarget[0];
@@ -87,6 +87,10 @@
         return targets.toArray(new RemoteAnimationTarget[targets.size()]);
     }
 
+    static boolean shouldStartWallpaperAnimation(DisplayContent displayContent) {
+        return displayContent.mWallpaperController.isWallpaperVisible();
+    }
+
     /**
      * Create a remote animation target for this animation adapter.
      */
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 08b1a2f..e24be37 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -611,8 +611,9 @@
     private void updateWallpaperTokens(boolean visible) {
         for (int curTokenNdx = mWallpaperTokens.size() - 1; curTokenNdx >= 0; curTokenNdx--) {
             final WallpaperWindowToken token = mWallpaperTokens.get(curTokenNdx);
-            token.updateWallpaperWindows(visible);
-            token.getDisplayContent().assignWindowLayers(false);
+            if (token.updateWallpaperWindows(visible)) {
+                token.mDisplayContent.assignWindowLayers(false /* setLayoutNeeded */);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index 3a639f5..fe405e5 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -104,18 +104,21 @@
         }
     }
 
-    void updateWallpaperWindows(boolean visible) {
+    /** Returns {@code true} if visibility is changed. */
+    boolean updateWallpaperWindows(boolean visible) {
+        boolean changed = false;
         if (isVisible() != visible) {
             ProtoLog.d(WM_DEBUG_WALLPAPER, "Wallpaper token %s visible=%b",
                     token, visible);
             setVisibility(visible);
+            changed = true;
         }
-        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
         if (mTransitionController.isShellTransitionsEnabled()) {
-            return;
+            return changed;
         }
 
-        final WindowState wallpaperTarget = wallpaperController.getWallpaperTarget();
+        final WindowState wallpaperTarget =
+                mDisplayContent.mWallpaperController.getWallpaperTarget();
 
         if (visible && wallpaperTarget != null) {
             final RecentsAnimationController recentsAnimationController =
@@ -137,6 +140,7 @@
         }
 
         setVisible(visible);
+        return changed;
     }
 
     private void setVisible(boolean visible) {
@@ -155,10 +159,12 @@
      * transition. In that situation, make sure to call {@link #commitVisibility} when done.
      */
     void setVisibility(boolean visible) {
-        // Before setting mVisibleRequested so we can track changes.
-        mTransitionController.collect(this);
+        if (mVisibleRequested != visible) {
+            // Before setting mVisibleRequested so we can track changes.
+            mTransitionController.collect(this);
 
-        setVisibleRequested(visible);
+            setVisibleRequested(visible);
+        }
 
         // If in a transition, defer commits for activities that are going invisible
         if (!visible && (mTransitionController.inTransition()
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 9865506..7e84dbb 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -2543,6 +2543,13 @@
         mSurfaceFreezer.unfreeze(getPendingTransaction());
     }
 
+    /** Whether we can start change transition with this window and current display status. */
+    boolean canStartChangeTransition() {
+        return !mWmService.mDisableTransitionAnimation && mDisplayContent != null
+                && getSurfaceControl() != null && !mDisplayContent.inTransition()
+                && isVisible() && isVisibleRequested() && okToAnimate();
+    }
+
     /**
      * Initializes a change transition. See {@link SurfaceFreezer} for more information.
      *
@@ -2891,12 +2898,7 @@
     }
 
     boolean okToAnimate() {
-        return okToAnimate(false /* ignoreFrozen */);
-    }
-
-    boolean okToAnimate(boolean ignoreFrozen) {
-        final DisplayContent dc = getDisplayContent();
-        return dc != null && dc.okToAnimate(ignoreFrozen);
+        return okToAnimate(false /* ignoreFrozen */, false /* ignoreScreenOn */);
     }
 
     boolean okToAnimate(boolean ignoreFrozen, boolean ignoreScreenOn) {
diff --git a/services/core/java/com/android/server/wm/WindowContextListenerController.java b/services/core/java/com/android/server/wm/WindowContextListenerController.java
index bc53041..cc52713 100644
--- a/services/core/java/com/android/server/wm/WindowContextListenerController.java
+++ b/services/core/java/com/android/server/wm/WindowContextListenerController.java
@@ -17,7 +17,9 @@
 package com.android.server.wm;
 
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.Display.isSuspendedState;
 import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
+import static android.window.WindowProviderService.isWindowProviderService;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
 import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
@@ -45,7 +47,7 @@
  *
  * <ul>
  *   <li>When a {@link WindowContext} is created, it registers the listener via
- *     {@link WindowManagerService#registerWindowContextListener(IBinder, int, int, Bundle)}
+ *     {@link WindowManagerService#attachWindowContextToDisplayArea(IBinder, int, int, Bundle)}
  *     automatically.</li>
  *   <li>When the {@link WindowContext} adds the first window to the screen via
  *     {@link android.view.WindowManager#addView(View, android.view.ViewGroup.LayoutParams)},
@@ -53,7 +55,7 @@
  *     to corresponding {@link WindowToken} via this controller.</li>
  *   <li>When the {@link WindowContext} is GCed, it unregisters the previously
  *     registered listener via
- *     {@link WindowManagerService#unregisterWindowContextListener(IBinder)}.
+ *     {@link WindowManagerService#detachWindowContextFromWindowContainer(IBinder)}.
  *     {@link WindowManagerService} is also responsible for removing the
  *     {@link WindowContext} created {@link WindowToken}.</li>
  * </ul>
@@ -68,7 +70,7 @@
 
     /**
      * Registers the listener to a {@code container} which is associated with
-     * a {@code clientToken}, which is a {@link android.app.WindowContext} representation. If the
+     * a {@code clientToken}, which is a {@link android.window.WindowContext} representation. If the
      * listener associated with {@code clientToken} hasn't been initialized yet, create one
      * {@link WindowContextListenerImpl}. Otherwise, the listener associated with
      * {@code clientToken} switches to listen to the {@code container}.
@@ -80,7 +82,7 @@
      * @param options a bundle used to pass window-related options.
      */
     void registerWindowContainerListener(@NonNull IBinder clientToken,
-            @NonNull WindowContainer container, int ownerUid, @WindowType int type,
+            @NonNull WindowContainer<?> container, int ownerUid, @WindowType int type,
             @Nullable Bundle options) {
         WindowContextListenerImpl listener = mListeners.get(clientToken);
         if (listener == null) {
@@ -103,6 +105,16 @@
         listener.unregister();
     }
 
+    void dispatchPendingConfigurationIfNeeded(int displayId) {
+        for (int i = mListeners.size() - 1; i >= 0; --i) {
+            final WindowContextListenerImpl listener = mListeners.valueAt(i);
+            if (listener.getWindowContainer().getDisplayContent().getDisplayId() == displayId
+                    && listener.mHasPendingConfiguration) {
+                listener.reportConfigToWindowTokenClient();
+            }
+        }
+    }
+
     /**
      * Verifies if the caller is allowed to do the operation to the listener specified by
      * {@code clientToken}.
@@ -138,7 +150,7 @@
         return listener != null ? listener.mOptions : null;
     }
 
-    @Nullable WindowContainer getContainer(IBinder clientToken) {
+    @Nullable WindowContainer<?> getContainer(IBinder clientToken) {
         final WindowContextListenerImpl listener = mListeners.get(clientToken);
         return listener != null ? listener.mContainer : null;
     }
@@ -163,7 +175,7 @@
     class WindowContextListenerImpl implements WindowContainerListener {
         @NonNull private final IBinder mClientToken;
         private final int mOwnerUid;
-        @NonNull private WindowContainer mContainer;
+        @NonNull private WindowContainer<?> mContainer;
         /**
          * The options from {@link Context#createWindowContext(int, Bundle)}.
          * <p>It can be used for choosing the {@link DisplayArea} where the window context
@@ -177,7 +189,9 @@
         private int mLastReportedDisplay = INVALID_DISPLAY;
         private Configuration mLastReportedConfig;
 
-        private WindowContextListenerImpl(IBinder clientToken, WindowContainer container,
+        private boolean mHasPendingConfiguration;
+
+        private WindowContextListenerImpl(IBinder clientToken, WindowContainer<?> container,
                 int ownerUid, @WindowType int type, @Nullable Bundle options) {
             mClientToken = clientToken;
             mContainer = Objects.requireNonNull(container);
@@ -197,11 +211,11 @@
 
         /** TEST ONLY: returns the {@link WindowContainer} of the listener */
         @VisibleForTesting
-        WindowContainer getWindowContainer() {
+        WindowContainer<?> getWindowContainer() {
             return mContainer;
         }
 
-        private void updateContainer(@NonNull WindowContainer newContainer) {
+        private void updateContainer(@NonNull WindowContainer<?> newContainer) {
             Objects.requireNonNull(newContainer);
 
             if (mContainer.equals(newContainer)) {
@@ -246,12 +260,20 @@
             if (mDeathRecipient == null) {
                 throw new IllegalStateException("Invalid client token: " + mClientToken);
             }
-
-            if (mLastReportedConfig == null) {
-                mLastReportedConfig = new Configuration();
+            // If the display of window context associated window container is suspended, don't
+            // report the configuration update. Note that we still dispatch the configuration update
+            // to WindowProviderService to make it compatible with Service#onConfigurationChanged.
+            // Service always receives #onConfigurationChanged callback regardless of display state.
+            if (!isWindowProviderService(mOptions)
+                    && isSuspendedState(mContainer.getDisplayContent().getDisplayInfo().state)) {
+                mHasPendingConfiguration = true;
+                return;
             }
             final Configuration config = mContainer.getConfiguration();
             final int displayId = mContainer.getDisplayContent().getDisplayId();
+            if (mLastReportedConfig == null) {
+                mLastReportedConfig = new Configuration();
+            }
             if (config.equals(mLastReportedConfig) && displayId == mLastReportedDisplay) {
                 // No changes since last reported time.
                 return;
@@ -266,6 +288,7 @@
             } catch (RemoteException e) {
                 ProtoLog.w(WM_ERROR, "Could not report config changes to the window token client.");
             }
+            mHasPendingConfiguration = false;
         }
 
         @Override
@@ -283,7 +306,7 @@
                 // If we cannot obtain the DisplayContent, the DisplayContent may also be removed.
                 // We should proceed the removal process.
                 if (dc != null) {
-                    final DisplayArea da = dc.findAreaForToken(windowToken);
+                    final DisplayArea<?> da = dc.findAreaForToken(windowToken);
                     updateContainer(da);
                     return;
                 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 4720d7c..23f9c58 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2700,6 +2700,9 @@
     @Override
     public Configuration attachWindowContextToDisplayArea(IBinder clientToken, int
             type, int displayId, Bundle options) {
+        if (clientToken == null) {
+            throw new IllegalArgumentException("clientToken must not be null!");
+        }
         final boolean callerCanManageAppTokens = checkCallingPermission(MANAGE_APP_TOKENS,
                 "attachWindowContextToDisplayArea", false /* printLog */);
         final int callingUid = Binder.getCallingUid();
@@ -2790,6 +2793,39 @@
         }
     }
 
+    @Override
+    public Configuration attachToDisplayContent(IBinder clientToken, int displayId) {
+        if (clientToken == null) {
+            throw new IllegalArgumentException("clientToken must not be null!");
+        }
+        final int callingUid = Binder.getCallingUid();
+        final long origId = Binder.clearCallingIdentity();
+        try {
+            synchronized (mGlobalLock) {
+                // We use "getDisplayContent" instead of "getDisplayContentOrCreate" because
+                // this method may be called in DisplayPolicy's constructor and may cause
+                // infinite loop. In this scenario, we early return here and switch to do the
+                // registration in DisplayContent#onParentChanged at DisplayContent initialization.
+                final DisplayContent dc = mRoot.getDisplayContent(displayId);
+                if (dc == null) {
+                    if (Binder.getCallingPid() != myPid()) {
+                        throw new WindowManager.InvalidDisplayException("attachToDisplayContent: "
+                                + "trying to attach to a non-existing display:" + displayId);
+                    }
+                    // Early return if this method is invoked from system process.
+                    // See above comments for more detail.
+                    return null;
+                }
+
+                mWindowContextListenerController.registerWindowContainerListener(clientToken, dc,
+                        callingUid, INVALID_WINDOW_TYPE, null /* options */);
+                return dc.getConfiguration();
+            }
+        } finally {
+            Binder.restoreCallingIdentity(origId);
+        }
+    }
+
     /** Returns {@code true} if this binder is a registered window token. */
     @Override
     public boolean isWindowToken(IBinder binder) {
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 3d479d1..0649b25 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -587,7 +587,7 @@
             case HIERARCHY_OP_TYPE_CREATE_TASK_FRAGMENT: {
                 final TaskFragmentCreationParams taskFragmentCreationOptions =
                         hop.getTaskFragmentCreationOptions();
-                createTaskFragment(taskFragmentCreationOptions, errorCallbackToken);
+                createTaskFragment(taskFragmentCreationOptions, errorCallbackToken, caller);
                 break;
             }
             case HIERARCHY_OP_TYPE_DELETE_TASK_FRAGMENT: {
@@ -630,7 +630,7 @@
                 final TaskFragment tf = mLaunchTaskFragments.get(fragmentToken);
                 final int result = mService.getActivityStartController()
                         .startActivityInTaskFragment(tf, activityIntent, activityOptions,
-                                hop.getCallingActivity());
+                                hop.getCallingActivity(), caller.mUid, caller.mPid);
                 if (!isStartResultSuccessful(result)) {
                     sendTaskFragmentOperationFailure(tf.getTaskFragmentOrganizer(),
                             errorCallbackToken,
@@ -1199,7 +1199,7 @@
     }
 
     void createTaskFragment(@NonNull TaskFragmentCreationParams creationParams,
-            @Nullable IBinder errorCallbackToken) {
+            @Nullable IBinder errorCallbackToken, @NonNull CallerInfo caller) {
         final ActivityRecord ownerActivity =
                 ActivityRecord.forTokenLocked(creationParams.getOwnerToken());
         final ITaskFragmentOrganizer organizer = ITaskFragmentOrganizer.Stub.asInterface(
@@ -1217,9 +1217,9 @@
             sendTaskFragmentOperationFailure(organizer, errorCallbackToken, exception);
             return;
         }
-        // The ownerActivity has to belong to the same app as the root Activity of the target Task.
-        final ActivityRecord rootActivity = ownerActivity.getTask().getRootActivity();
-        if (rootActivity.getUid() != ownerActivity.getUid()) {
+        // The ownerActivity has to belong to the same app as the target Task.
+        if (ownerActivity.getTask().effectiveUid != ownerActivity.getUid()
+                || ownerActivity.getTask().effectiveUid != caller.mUid) {
             final Throwable exception =
                     new IllegalArgumentException("Not allowed to operate with the ownerToken while "
                             + "the root activity of the target task belong to the different app");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 81b241e..bae5465 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -48,7 +48,6 @@
 import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
 import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
@@ -1338,8 +1337,7 @@
         outFrame.set(0, 0, mWindowFrames.mCompatFrame.width(), mWindowFrames.mCompatFrame.height());
     }
 
-    @Override
-    public WindowManager.LayoutParams getAttrs() {
+    WindowManager.LayoutParams getAttrs() {
         return mAttrs;
     }
 
@@ -2687,10 +2685,9 @@
         }
     }
 
-    int getSurfaceTouchableRegion(Region region, int flags) {
-        final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
+    void getSurfaceTouchableRegion(Region region, WindowManager.LayoutParams attrs) {
+        final boolean modal = attrs.isModal();
         if (modal) {
-            flags |= FLAG_NOT_TOUCH_MODAL;
             if (mActivityRecord != null) {
                 // Limit the outer touch to the activity root task region.
                 updateRegionForModalActivityWindow(region);
@@ -2722,8 +2719,6 @@
         if (mInvGlobalScale != 1.f) {
             region.scale(mInvGlobalScale);
         }
-
-        return flags;
     }
 
     /**
@@ -3414,7 +3409,10 @@
         }
         // Exclude toast because legacy apps may show toast window by themselves, so the misused
         // apps won't always be considered as foreground state.
-        if (mAttrs.type >= FIRST_SYSTEM_WINDOW && mAttrs.type != TYPE_TOAST) {
+        // Exclude private presentations as they can only be shown on private virtual displays and
+        // shouldn't be the cause of an app be considered foreground.
+        if (mAttrs.type >= FIRST_SYSTEM_WINDOW && mAttrs.type != TYPE_TOAST
+                && mAttrs.type != TYPE_PRIVATE_PRESENTATION) {
             mWmService.mAtmService.mActiveUids.onNonAppSurfaceVisibilityChanged(mOwnerUid, shown);
         }
     }
@@ -3559,10 +3557,9 @@
      * {@link WindowManager.LayoutParams#FLAG_NOT_TOUCH_MODAL touch modality.}
      */
     void getEffectiveTouchableRegion(Region outRegion) {
-        final boolean modal = (mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
         final DisplayContent dc = getDisplayContent();
 
-        if (modal && dc != null) {
+        if (mAttrs.isModal() && dc != null) {
             outRegion.set(dc.getBounds());
             cropRegionToRootTaskBoundsIfNeeded(outRegion);
             subtractTouchExcludeRegionIfNeeded(outRegion);
@@ -3835,6 +3832,24 @@
         return (mAttrs.insetsFlags.behavior & BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE) != 0;
     }
 
+    boolean canBeHiddenByKeyguard() {
+        // Keyguard visibility of window from activities are determined over activity visibility.
+        if (mActivityRecord != null) {
+            return false;
+        }
+        switch (mAttrs.type) {
+            case TYPE_NOTIFICATION_SHADE:
+            case TYPE_STATUS_BAR:
+            case TYPE_NAVIGATION_BAR:
+            case TYPE_WALLPAPER:
+                return false;
+            default:
+                // Hide only windows below the keyguard host window.
+                return mPolicy.getWindowLayerLw(this)
+                        < mPolicy.getWindowLayerFromTypeLw(TYPE_NOTIFICATION_SHADE);
+        }
+    }
+
     private int getRootTaskId() {
         final Task rootTask = getRootTask();
         if (rootTask == null) {
@@ -4710,6 +4725,48 @@
         return false;
     }
 
+    private boolean shouldFinishAnimatingExit() {
+        // Exit animation might be applied soon.
+        if (inTransition()) {
+            ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isTransition: %s",
+                    this);
+            return false;
+        }
+        if (!mDisplayContent.okToAnimate()) {
+            return true;
+        }
+        // Exit animation is running.
+        if (isAnimating(TRANSITION | PARENTS, EXIT_ANIMATING_TYPES)) {
+            ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "shouldWaitAnimatingExit: isAnimating: %s",
+                    this);
+            return false;
+        }
+        // If the wallpaper is currently behind this app window, we need to change both of
+        // them inside of a transaction to avoid artifacts.
+        if (mDisplayContent.mWallpaperController.isWallpaperTarget(this)) {
+            ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
+                    "shouldWaitAnimatingExit: isWallpaperTarget: %s", this);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * If this is window is stuck in the animatingExit status, resume clean up procedure blocked
+     * by the exit animation.
+     */
+    void cleanupAnimatingExitWindow() {
+        // TODO(b/205335975): WindowManagerService#tryStartExitingAnimation starts an exit animation
+        // and set #mAnimationExit. After the exit animation finishes, #onExitAnimationDone shall
+        // be called, but there seems to be a case that #onExitAnimationDone is not triggered, so
+        // a windows stuck in the animatingExit status.
+        if (mAnimatingExit && shouldFinishAnimatingExit()) {
+            ProtoLog.w(WM_DEBUG_APP_TRANSITIONS, "Clear window stuck on animatingExit status: %s",
+                    this);
+            onExitAnimationDone();
+        }
+    }
+
     void onExitAnimationDone() {
         if (DEBUG_ANIM) Slog.v(TAG, "onExitAnimationDone in " + this
                 + ": exiting=" + mAnimatingExit + " remove=" + mRemoveOnExit
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index b1cad7c..318ad06 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -295,6 +295,9 @@
         // surface for this token.
         if (mSurfaceControl == null) {
             createSurfaceControl(true /* force */);
+
+            // Layers could have been assigned before the surface was created, update them again
+            reassignLayer(getSyncTransaction());
         }
         if (!mChildren.contains(win)) {
             ProtoLog.v(WM_DEBUG_ADD_REMOVE, "Adding %s to %s", win, this);
diff --git a/services/core/java/com/android/server/wm/WindowTracing.java b/services/core/java/com/android/server/wm/WindowTracing.java
index 6204824..ca834c5 100644
--- a/services/core/java/com/android/server/wm/WindowTracing.java
+++ b/services/core/java/com/android/server/wm/WindowTracing.java
@@ -48,12 +48,12 @@
 class WindowTracing {
 
     /**
-     * Maximum buffer size, currently defined as 512 KB
+     * Maximum buffer size, currently defined as 5 MB
      * Size was experimentally defined to fit between 100 to 150 elements.
      */
-    private static final int BUFFER_CAPACITY_CRITICAL = 512 * 1024;
-    private static final int BUFFER_CAPACITY_TRIM = 2048 * 1024;
-    private static final int BUFFER_CAPACITY_ALL = 4096 * 1024;
+    private static final int BUFFER_CAPACITY_CRITICAL = 5120 * 1024; // 5 MB
+    private static final int BUFFER_CAPACITY_TRIM = 10240 * 1024; // 10 MB
+    private static final int BUFFER_CAPACITY_ALL = 20480 * 1024; // 20 MB
     static final String WINSCOPE_EXT = ".winscope";
     private static final String TRACE_FILENAME = "/data/misc/wmtrace/wm_trace" + WINSCOPE_EXT;
     private static final String TAG = "WindowTracing";
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 6be872f..2ccef9a 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -28,8 +28,9 @@
 #include <android/hardware/gnss/2.1/IGnssAntennaInfo.h>
 #include <android/hardware/gnss/2.1/IGnssMeasurement.h>
 #include <android/hardware/gnss/BnGnss.h>
-#include <android/hardware/gnss/BnGnssBatchingCallback.h>
 #include <android/hardware/gnss/BnGnssCallback.h>
+#include <android/hardware/gnss/BnGnssGeofence.h>
+#include <android/hardware/gnss/BnGnssGeofenceCallback.h>
 #include <android/hardware/gnss/BnGnssMeasurementCallback.h>
 #include <android/hardware/gnss/BnGnssPowerIndicationCallback.h>
 #include <android/hardware/gnss/BnGnssPsdsCallback.h>
@@ -52,20 +53,18 @@
 #include "android_runtime/AndroidRuntime.h"
 #include "android_runtime/Log.h"
 #include "gnss/GnssAntennaInfoCallback.h"
+#include "gnss/GnssBatching.h"
 #include "gnss/GnssConfiguration.h"
 #include "gnss/GnssMeasurement.h"
+#include "gnss/GnssNavigationMessage.h"
 #include "gnss/Utils.h"
 #include "hardware_legacy/power.h"
 #include "jni.h"
 #include "utils/Log.h"
 #include "utils/misc.h"
 
-static jclass class_location;
-static jclass class_gnssNavigationMessage;
 static jclass class_gnssPowerStats;
 
-jobject android::mCallbacksObj = nullptr;
-
 static jmethodID method_reportLocation;
 static jmethodID method_reportStatus;
 static jmethodID method_reportSvStatus;
@@ -86,8 +85,6 @@
 static jmethodID method_reportGeofenceRemoveStatus;
 static jmethodID method_reportGeofencePauseStatus;
 static jmethodID method_reportGeofenceResumeStatus;
-static jmethodID method_reportNavigationMessages;
-static jmethodID method_reportLocationBatch;
 static jmethodID method_reportGnssServiceDied;
 static jmethodID method_reportGnssPowerStats;
 static jmethodID method_setSubHalMeasurementCorrectionsCapabilities;
@@ -117,8 +114,6 @@
 static jmethodID method_correctionPlaneAzimDeg;
 static jmethodID method_reportNfwNotification;
 static jmethodID method_isInEmergencySession;
-static jmethodID method_locationCtor;
-static jmethodID method_gnssNavigationMessageCtor;
 static jmethodID method_gnssPowerStatsCtor;
 static jmethodID method_setSubHalPowerIndicationCapabilities;
 
@@ -179,10 +174,6 @@
 using IAGnss_V2_0 = android::hardware::gnss::V2_0::IAGnss;
 using IAGnssCallback_V1_0 = android::hardware::gnss::V1_0::IAGnssCallback;
 using IAGnssCallback_V2_0 = android::hardware::gnss::V2_0::IAGnssCallback;
-using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching;
-using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching;
-using IGnssBatchingCallback_V1_0 = android::hardware::gnss::V1_0::IGnssBatchingCallback;
-using IGnssBatchingCallback_V2_0 = android::hardware::gnss::V2_0::IGnssBatchingCallback;
 
 using IMeasurementCorrections_V1_0 = android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
 using IMeasurementCorrections_V1_1 = android::hardware::gnss::measurement_corrections::V1_1::IMeasurementCorrections;
@@ -199,9 +190,10 @@
 using android::hardware::gnss::IGnssPowerIndicationCallback;
 using android::hardware::gnss::PsdsType;
 using IGnssAidl = android::hardware::gnss::IGnss;
-using IGnssBatchingAidl = android::hardware::gnss::IGnssBatching;
-using IGnssBatchingCallbackAidl = android::hardware::gnss::IGnssBatchingCallback;
 using IGnssCallbackAidl = android::hardware::gnss::IGnssCallback;
+using IGnssBatchingAidl = android::hardware::gnss::IGnssBatching;
+using IGnssGeofenceAidl = android::hardware::gnss::IGnssGeofence;
+using IGnssGeofenceCallbackAidl = android::hardware::gnss::IGnssGeofenceCallback;
 using IGnssPsdsAidl = android::hardware::gnss::IGnssPsds;
 using IGnssPsdsCallbackAidl = android::hardware::gnss::IGnssPsdsCallback;
 using IGnssConfigurationAidl = android::hardware::gnss::IGnssConfiguration;
@@ -228,6 +220,7 @@
 sp<IGnss_V2_1> gnssHal_V2_1 = nullptr;
 sp<IGnssAidl> gnssHalAidl = nullptr;
 sp<IGnssBatchingAidl> gnssBatchingAidlIface = nullptr;
+sp<IGnssGeofenceAidl> gnssGeofenceAidlIface = nullptr;
 sp<IGnssPsdsAidl> gnssPsdsAidlIface = nullptr;
 sp<IGnssXtra> gnssXtraIface = nullptr;
 sp<IAGnssRil_V1_0> agnssRilIface = nullptr;
@@ -235,12 +228,9 @@
 sp<IGnssGeofencing> gnssGeofencingIface = nullptr;
 sp<IAGnss_V1_0> agnssIface = nullptr;
 sp<IAGnss_V2_0> agnssIface_V2_0 = nullptr;
-sp<IGnssBatching_V1_0> gnssBatchingIface = nullptr;
-sp<IGnssBatching_V2_0> gnssBatchingIface_V2_0 = nullptr;
 sp<IGnssDebug_V1_0> gnssDebugIface = nullptr;
 sp<IGnssDebug_V2_0> gnssDebugIface_V2_0 = nullptr;
 sp<IGnssNi> gnssNiIface = nullptr;
-sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
 sp<IGnssPowerIndication> gnssPowerIndicationIface = nullptr;
 sp<IMeasurementCorrections_V1_0> gnssCorrectionsIface_V1_0 = nullptr;
 sp<IMeasurementCorrections_V1_1> gnssCorrectionsIface_V1_1 = nullptr;
@@ -249,6 +239,8 @@
 
 std::unique_ptr<GnssConfigurationInterface> gnssConfigurationIface = nullptr;
 std::unique_ptr<android::gnss::GnssMeasurementInterface> gnssMeasurementIface = nullptr;
+std::unique_ptr<android::gnss::GnssNavigationMessageInterface> gnssNavigationMessageIface = nullptr;
+std::unique_ptr<android::gnss::GnssBatchingInterface> gnssBatchingIface = nullptr;
 
 #define WAKE_LOCK_NAME  "GPS"
 
@@ -301,103 +293,6 @@
     const char* mNativeString;
 };
 
-static jobject translateGnssLocation(JNIEnv* env, const GnssLocationAidl& location) {
-    JavaObject object(env, class_location, method_locationCtor, "gps");
-
-    uint32_t flags = static_cast<uint32_t>(location.gnssLocationFlags);
-    if (flags & GnssLocationAidl::HAS_LAT_LONG) {
-        SET(Latitude, location.latitudeDegrees);
-        SET(Longitude, location.longitudeDegrees);
-    }
-    if (flags & GnssLocationAidl::HAS_ALTITUDE) {
-        SET(Altitude, location.altitudeMeters);
-    }
-    if (flags & GnssLocationAidl::HAS_SPEED) {
-        SET(Speed, (float)location.speedMetersPerSec);
-    }
-    if (flags & GnssLocationAidl::HAS_BEARING) {
-        SET(Bearing, (float)location.bearingDegrees);
-    }
-    if (flags & GnssLocationAidl::HAS_HORIZONTAL_ACCURACY) {
-        SET(Accuracy, (float)location.horizontalAccuracyMeters);
-    }
-    if (flags & GnssLocationAidl::HAS_VERTICAL_ACCURACY) {
-        SET(VerticalAccuracyMeters, (float)location.verticalAccuracyMeters);
-    }
-    if (flags & GnssLocationAidl::HAS_SPEED_ACCURACY) {
-        SET(SpeedAccuracyMetersPerSecond, (float)location.speedAccuracyMetersPerSecond);
-    }
-    if (flags & GnssLocationAidl::HAS_BEARING_ACCURACY) {
-        SET(BearingAccuracyDegrees, (float)location.bearingAccuracyDegrees);
-    }
-    SET(Time, location.timestampMillis);
-
-    flags = static_cast<uint32_t>(location.elapsedRealtime.flags);
-    if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIMESTAMP_NS) {
-        SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs);
-    }
-    if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS) {
-        SET(ElapsedRealtimeUncertaintyNanos,
-            static_cast<double>(location.elapsedRealtime.timeUncertaintyNs));
-    }
-
-    return object.get();
-}
-
-static jobject translateGnssLocation(JNIEnv* env,
-                                     const GnssLocation_V1_0& location) {
-    JavaObject object(env, class_location, method_locationCtor, "gps");
-
-    uint16_t flags = static_cast<uint16_t>(location.gnssLocationFlags);
-    if (flags & GnssLocationFlags::HAS_LAT_LONG) {
-        SET(Latitude, location.latitudeDegrees);
-        SET(Longitude, location.longitudeDegrees);
-    }
-    if (flags & GnssLocationFlags::HAS_ALTITUDE) {
-        SET(Altitude, location.altitudeMeters);
-    }
-    if (flags & GnssLocationFlags::HAS_SPEED) {
-        SET(Speed, location.speedMetersPerSec);
-    }
-    if (flags & GnssLocationFlags::HAS_BEARING) {
-        SET(Bearing, location.bearingDegrees);
-    }
-    if (flags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
-        SET(Accuracy, location.horizontalAccuracyMeters);
-    }
-    if (flags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
-        SET(VerticalAccuracyMeters, location.verticalAccuracyMeters);
-    }
-    if (flags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
-        SET(SpeedAccuracyMetersPerSecond, location.speedAccuracyMetersPerSecond);
-    }
-    if (flags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
-        SET(BearingAccuracyDegrees, location.bearingAccuracyDegrees);
-    }
-    SET(Time, location.timestamp);
-    SET(ElapsedRealtimeNanos, android::elapsedRealtimeNano());
-
-    return object.get();
-}
-
-static jobject translateGnssLocation(JNIEnv* env,
-                                     const GnssLocation_V2_0& location) {
-    JavaObject object(env, class_location, translateGnssLocation(env, location.v1_0));
-
-    const uint16_t flags = static_cast<uint16_t>(location.elapsedRealtime.flags);
-
-    // Overwrite ElapsedRealtimeNanos when available from HAL.
-    if (flags & ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
-        SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs);
-    }
-
-    if (flags & ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
-        SET(ElapsedRealtimeUncertaintyNanos, static_cast<double>(location.elapsedRealtime.timeUncertaintyNs));
-    }
-
-    return object.get();
-}
-
 static GnssLocation_V1_0 createGnssLocation_V1_0(
         jint gnssLocationFlags, jdouble latitudeDegrees, jdouble longitudeDegrees,
         jdouble altitudeMeters, jfloat speedMetersPerSec, jfloat bearingDegrees,
@@ -819,35 +714,25 @@
     return Void();
 }
 
-/*
- * GnssGeofenceCallback class implements the callback methods for the
- * IGnssGeofence interface.
- */
-struct GnssGeofenceCallback : public IGnssGeofenceCallback {
-    // Methods from ::android::hardware::gps::V1_0::IGnssGeofenceCallback follow.
-    Return<void> gnssGeofenceTransitionCb(
-            int32_t geofenceId,
-            const GnssLocation_V1_0& location,
-            GeofenceTransition transition,
-            hardware::gnss::V1_0::GnssUtcTime timestamp) override;
-    Return<void>
-    gnssGeofenceStatusCb(
-            GeofenceAvailability status,
-            const GnssLocation_V1_0& location) override;
-    Return<void> gnssGeofenceAddCb(int32_t geofenceId,
-                                   GeofenceStatus status) override;
-    Return<void> gnssGeofenceRemoveCb(int32_t geofenceId,
-                                      GeofenceStatus status) override;
-    Return<void> gnssGeofencePauseCb(int32_t geofenceId,
-                                     GeofenceStatus status) override;
-    Return<void> gnssGeofenceResumeCb(int32_t geofenceId,
-                                      GeofenceStatus status) override;
+/** Util class for GnssGeofenceCallback methods. */
+struct GnssGeofenceCallbackUtil {
+    template <class T>
+    static void gnssGeofenceTransitionCb(int geofenceId, const T& location, int transition,
+                                         int64_t timestampMillis);
+    template <class T>
+    static void gnssGeofenceStatusCb(int availability, const T& lastLocation);
+    static void gnssGeofenceAddCb(int geofenceId, int status);
+    static void gnssGeofenceRemoveCb(int geofenceId, int status);
+    static void gnssGeofencePauseCb(int geofenceId, int status);
+    static void gnssGeofenceResumeCb(int geofenceId, int status);
+
+private:
+    GnssGeofenceCallbackUtil() = delete;
 };
 
-Return<void> GnssGeofenceCallback::gnssGeofenceTransitionCb(
-        int32_t geofenceId, const GnssLocation_V1_0& location,
-        GeofenceTransition transition,
-        hardware::gnss::V1_0::GnssUtcTime timestamp) {
+template <class T>
+void GnssGeofenceCallbackUtil::gnssGeofenceTransitionCb(int geofenceId, const T& location,
+                                                        int transition, int64_t timestamp) {
     JNIEnv* env = getJniEnv();
 
     jobject jLocation = translateGnssLocation(env, location);
@@ -861,27 +746,22 @@
 
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     env->DeleteLocalRef(jLocation);
-    return Void();
 }
 
-Return<void>
-GnssGeofenceCallback::gnssGeofenceStatusCb(GeofenceAvailability status,
-                                           const GnssLocation_V1_0& location) {
+template <class T>
+void GnssGeofenceCallbackUtil::gnssGeofenceStatusCb(int availability, const T& lastLocation) {
     JNIEnv* env = getJniEnv();
 
-    jobject jLocation = translateGnssLocation(env, location);
+    jobject jLocation = translateGnssLocation(env, lastLocation);
 
-    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, status,
-                        jLocation);
+    env->CallVoidMethod(mCallbacksObj, method_reportGeofenceStatus, availability, jLocation);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
     env->DeleteLocalRef(jLocation);
-    return Void();
 }
 
-Return<void> GnssGeofenceCallback::gnssGeofenceAddCb(int32_t geofenceId,
-                                                    GeofenceStatus status) {
+void GnssGeofenceCallbackUtil::gnssGeofenceAddCb(int geofenceId, int status) {
     JNIEnv* env = getJniEnv();
-    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+    if (status != IGnssGeofenceCallbackAidl::OPERATION_SUCCESS) {
         ALOGE("%s: Error in adding a Geofence: %d\n", __func__, status);
     }
 
@@ -890,13 +770,11 @@
                         geofenceId,
                         status);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return Void();
 }
 
-Return<void> GnssGeofenceCallback::gnssGeofenceRemoveCb(int32_t geofenceId,
-                                                       GeofenceStatus status) {
+void GnssGeofenceCallbackUtil::gnssGeofenceRemoveCb(int geofenceId, int status) {
     JNIEnv* env = getJniEnv();
-    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+    if (status != IGnssGeofenceCallbackAidl::OPERATION_SUCCESS) {
         ALOGE("%s: Error in removing a Geofence: %d\n", __func__, status);
     }
 
@@ -904,13 +782,11 @@
                         method_reportGeofenceRemoveStatus,
                         geofenceId, status);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return Void();
 }
 
-Return<void> GnssGeofenceCallback::gnssGeofencePauseCb(int32_t geofenceId,
-                                                      GeofenceStatus status) {
+void GnssGeofenceCallbackUtil::gnssGeofencePauseCb(int geofenceId, int status) {
     JNIEnv* env = getJniEnv();
-    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+    if (status != IGnssGeofenceCallbackAidl::OPERATION_SUCCESS) {
         ALOGE("%s: Error in pausing Geofence: %d\n", __func__, status);
     }
 
@@ -918,13 +794,11 @@
                         method_reportGeofencePauseStatus,
                         geofenceId, status);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return Void();
 }
 
-Return<void> GnssGeofenceCallback::gnssGeofenceResumeCb(int32_t geofenceId,
-                                                       GeofenceStatus status) {
+void GnssGeofenceCallbackUtil::gnssGeofenceResumeCb(int geofenceId, int status) {
     JNIEnv* env = getJniEnv();
-    if (status != IGnssGeofenceCallback::GeofenceStatus::OPERATION_SUCCESS) {
+    if (status != IGnssGeofenceCallbackAidl::OPERATION_SUCCESS) {
         ALOGE("%s: Error in resuming Geofence: %d\n", __func__, status);
     }
 
@@ -932,50 +806,104 @@
                         method_reportGeofenceResumeStatus,
                         geofenceId, status);
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    return Void();
 }
 
 /*
- * GnssNavigationMessageCallback interface implements the callback methods
- * required by the IGnssNavigationMessage interface.
+ * GnssGeofenceCallbackAidl class implements the callback methods for the IGnssGeofence AIDL
+ * interface.
  */
-struct GnssNavigationMessageCallback : public IGnssNavigationMessageCallback {
-  /*
-   * Methods from ::android::hardware::gps::V1_0::IGnssNavigationMessageCallback
-   * follow.
-   */
-  Return<void> gnssNavigationMessageCb(
-          const IGnssNavigationMessageCallback::GnssNavigationMessage& message) override;
+struct GnssGeofenceCallbackAidl : public android::hardware::gnss::BnGnssGeofenceCallback {
+    Status gnssGeofenceTransitionCb(int geofenceId, const GnssLocationAidl& location,
+                                    int transition, int64_t timestampMillis) override;
+    Status gnssGeofenceStatusCb(int availability, const GnssLocationAidl& lastLocation) override;
+    Status gnssGeofenceAddCb(int geofenceId, int status) override;
+    Status gnssGeofenceRemoveCb(int geofenceId, int status) override;
+    Status gnssGeofencePauseCb(int geofenceId, int status) override;
+    Status gnssGeofenceResumeCb(int geofenceId, int status) override;
 };
 
-Return<void> GnssNavigationMessageCallback::gnssNavigationMessageCb(
-        const IGnssNavigationMessageCallback::GnssNavigationMessage& message) {
-    JNIEnv* env = getJniEnv();
+Status GnssGeofenceCallbackAidl::gnssGeofenceTransitionCb(int geofenceId,
+                                                          const GnssLocationAidl& location,
+                                                          int transition, int64_t timestampMillis) {
+    GnssGeofenceCallbackUtil::gnssGeofenceTransitionCb(geofenceId, location, transition,
+                                                       timestampMillis);
+    return Status::ok();
+}
 
-    size_t dataLength = message.data.size();
+Status GnssGeofenceCallbackAidl::gnssGeofenceStatusCb(int availability,
+                                                      const GnssLocationAidl& lastLocation) {
+    GnssGeofenceCallbackUtil::gnssGeofenceStatusCb(availability, lastLocation);
+    return Status::ok();
+}
 
-    std::vector<uint8_t> navigationData = message.data;
-    uint8_t* data = &(navigationData[0]);
-    if (dataLength == 0 || data == nullptr) {
-      ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data,
-            dataLength);
-      return Void();
-    }
+Status GnssGeofenceCallbackAidl::gnssGeofenceAddCb(int geofenceId, int status) {
+    GnssGeofenceCallbackUtil::gnssGeofenceAddCb(geofenceId, status);
+    return Status::ok();
+}
 
-    JavaObject object(env, class_gnssNavigationMessage, method_gnssNavigationMessageCtor);
-    SET(Type, static_cast<int32_t>(message.type));
-    SET(Svid, static_cast<int32_t>(message.svid));
-    SET(MessageId, static_cast<int32_t>(message.messageId));
-    SET(SubmessageId, static_cast<int32_t>(message.submessageId));
-    object.callSetter("setData", data, dataLength);
-    SET(Status, static_cast<int32_t>(message.status));
+Status GnssGeofenceCallbackAidl::gnssGeofenceRemoveCb(int geofenceId, int status) {
+    GnssGeofenceCallbackUtil::gnssGeofenceRemoveCb(geofenceId, status);
+    return Status::ok();
+}
 
-    jobject navigationMessage = object.get();
-    env->CallVoidMethod(mCallbacksObj,
-                        method_reportNavigationMessages,
-                        navigationMessage);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-    env->DeleteLocalRef(navigationMessage);
+Status GnssGeofenceCallbackAidl::gnssGeofencePauseCb(int geofenceId, int status) {
+    GnssGeofenceCallbackUtil::gnssGeofencePauseCb(geofenceId, status);
+    return Status::ok();
+}
+
+Status GnssGeofenceCallbackAidl::gnssGeofenceResumeCb(int geofenceId, int status) {
+    GnssGeofenceCallbackUtil::gnssGeofenceResumeCb(geofenceId, status);
+    return Status::ok();
+}
+
+/*
+ * GnssGeofenceCallback class implements the callback methods for the
+ * IGnssGeofence HIDL interface.
+ */
+struct GnssGeofenceCallback : public IGnssGeofenceCallback {
+    // Methods from ::android::hardware::gps::V1_0::IGnssGeofenceCallback follow.
+    Return<void> gnssGeofenceTransitionCb(int32_t geofenceId, const GnssLocation_V1_0& location,
+                                          GeofenceTransition transition,
+                                          hardware::gnss::V1_0::GnssUtcTime timestamp) override;
+    Return<void> gnssGeofenceStatusCb(GeofenceAvailability status,
+                                      const GnssLocation_V1_0& location) override;
+    Return<void> gnssGeofenceAddCb(int32_t geofenceId, GeofenceStatus status) override;
+    Return<void> gnssGeofenceRemoveCb(int32_t geofenceId, GeofenceStatus status) override;
+    Return<void> gnssGeofencePauseCb(int32_t geofenceId, GeofenceStatus status) override;
+    Return<void> gnssGeofenceResumeCb(int32_t geofenceId, GeofenceStatus status) override;
+};
+
+Return<void> GnssGeofenceCallback::gnssGeofenceTransitionCb(
+        int32_t geofenceId, const GnssLocation_V1_0& location, GeofenceTransition transition,
+        hardware::gnss::V1_0::GnssUtcTime timestamp) {
+    GnssGeofenceCallbackUtil::gnssGeofenceTransitionCb(geofenceId, location, (int)transition,
+                                                       (int64_t)timestamp);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceStatusCb(GeofenceAvailability availability,
+                                                        const GnssLocation_V1_0& location) {
+    GnssGeofenceCallbackUtil::gnssGeofenceStatusCb((int)availability, location);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceAddCb(int32_t geofenceId, GeofenceStatus status) {
+    GnssGeofenceCallbackUtil::gnssGeofenceAddCb(geofenceId, (int)status);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceRemoveCb(int32_t geofenceId, GeofenceStatus status) {
+    GnssGeofenceCallbackUtil::gnssGeofenceRemoveCb(geofenceId, (int)status);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofencePauseCb(int32_t geofenceId, GeofenceStatus status) {
+    GnssGeofenceCallbackUtil::gnssGeofencePauseCb(geofenceId, (int)status);
+    return Void();
+}
+
+Return<void> GnssGeofenceCallback::gnssGeofenceResumeCb(int32_t geofenceId, GeofenceStatus status) {
+    GnssGeofenceCallbackUtil::gnssGeofenceResumeCb(geofenceId, (int)status);
     return Void();
 }
 
@@ -1219,66 +1147,6 @@
     return Void();
 }
 
-struct GnssBatchingCallbackUtil {
-    template<class T>
-    static Return<void> gnssLocationBatchCbImpl(const hidl_vec<T>& locations);
-private:
-    GnssBatchingCallbackUtil() = delete;
-};
-
-template<class T>
-Return<void> GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(const hidl_vec<T>& locations) {
-    JNIEnv* env = getJniEnv();
-
-    jobjectArray jLocations = env->NewObjectArray(locations.size(), class_location, nullptr);
-
-    for (uint16_t i = 0; i < locations.size(); ++i) {
-        jobject jLocation = translateGnssLocation(env, locations[i]);
-        env->SetObjectArrayElement(jLocations, i, jLocation);
-        env->DeleteLocalRef(jLocation);
-    }
-
-    env->CallVoidMethod(mCallbacksObj, method_reportLocationBatch, jLocations);
-    checkAndClearExceptionFromCallback(env, __FUNCTION__);
-
-    env->DeleteLocalRef(jLocations);
-
-    return Void();
-}
-
-/*
- * GnssBatchingCallbackAidl class implements the callback methods required by the
- * android::hardware::gnss::IGnssBatching interface.
- */
-struct GnssBatchingCallbackAidl : public android::hardware::gnss::BnGnssBatchingCallback {
-    Status gnssLocationBatchCb(const std::vector<GnssLocationAidl>& locations) {
-        GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(hidl_vec<GnssLocationAidl>(locations));
-        return Status::ok();
-    }
-};
-
-/*
- * GnssBatchingCallback_V1_0 class implements the callback methods required by the
- * IGnssBatching 1.0 interface.
- */
-struct GnssBatchingCallback_V1_0 : public IGnssBatchingCallback_V1_0 {
-    /** Methods from ::android::hardware::gps::V1_0::IGnssBatchingCallback follow. */
-    Return<void> gnssLocationBatchCb(const hidl_vec<GnssLocation_V1_0>& locations) override {
-        return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations);
-    }
-};
-
-/*
- * GnssBatchingCallback_V2_0 class implements the callback methods required by the
- * IGnssBatching 2.0 interface.
- */
-struct GnssBatchingCallback_V2_0 : public IGnssBatchingCallback_V2_0 {
-    /** Methods from ::android::hardware::gps::V2_0::IGnssBatchingCallback follow. */
-    Return<void> gnssLocationBatchCb(const hidl_vec<GnssLocation_V2_0>& locations) override {
-        return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations);
-    }
-};
-
 /* Initializes the GNSS service handle. */
 static void android_location_gnss_hal_GnssNative_set_gps_service_handle() {
     gnssHalAidl = waitForVintfService<IGnssAidl>();
@@ -1350,14 +1218,6 @@
             "(II)V");
     method_reportGeofencePauseStatus = env->GetMethodID(clazz, "reportGeofencePauseStatus",
             "(II)V");
-    method_reportNavigationMessages = env->GetMethodID(
-            clazz,
-            "reportNavigationMessage",
-            "(Landroid/location/GnssNavigationMessage;)V");
-    method_reportLocationBatch = env->GetMethodID(
-            clazz,
-            "reportLocationBatch",
-            "([Landroid/location/Location;)V");
     method_reportGnssServiceDied = env->GetMethodID(clazz, "reportGnssServiceDied", "()V");
     method_reportNfwNotification = env->GetMethodID(clazz, "reportNfwNotification",
             "(Ljava/lang/String;BLjava/lang/String;BLjava/lang/String;BZZ)V");
@@ -1427,17 +1287,12 @@
     class_gnssPowerStats = (jclass)env->NewGlobalRef(gnssPowerStatsClass);
     method_gnssPowerStatsCtor = env->GetMethodID(class_gnssPowerStats, "<init>", "(IJDDDDDD[D)V");
 
-    jclass locationClass = env->FindClass("android/location/Location");
-    class_location = (jclass) env->NewGlobalRef(locationClass);
-    method_locationCtor = env->GetMethodID(class_location, "<init>", "(Ljava/lang/String;)V");
-
-    jclass gnssNavigationMessageClass = env->FindClass("android/location/GnssNavigationMessage");
-    class_gnssNavigationMessage = (jclass) env->NewGlobalRef(gnssNavigationMessageClass);
-    method_gnssNavigationMessageCtor = env->GetMethodID(class_gnssNavigationMessage, "<init>", "()V");
-
+    gnss::GnssAntennaInfo_class_init_once(env, clazz);
+    gnss::GnssBatching_class_init_once(env, clazz);
     gnss::GnssConfiguration_class_init_once(env);
     gnss::GnssMeasurement_class_init_once(env, clazz);
-    gnss::GnssAntennaInfo_class_init_once(env, clazz);
+    gnss::GnssNavigationMessage_class_init_once(env, clazz);
+    gnss::Utils_class_init_once(env);
 }
 
 /* Initialization needed at system boot and whenever GNSS service dies. */
@@ -1455,11 +1310,13 @@
         android_location_gnss_hal_GnssNative_set_gps_service_handle();
     }
 
-    if (gnssHal == nullptr) {
+    if (gnssHal == nullptr && gnssHalAidl == nullptr) {
         ALOGE("Unable to get GPS service\n");
         return;
     }
 
+    // TODO: linkToDeath for AIDL HAL
+
     gnssHalDeathRecipient = new GnssDeathRecipient();
     hardware::Return<bool> linked = gnssHal->linkToDeath(gnssHalDeathRecipient, /*cookie*/ 0);
     if (!linked.isOk()) {
@@ -1479,7 +1336,7 @@
         } else {
             ALOGD("Unable to get a handle to PSDS AIDL interface.");
         }
-    } else {
+    } else if (gnssHal != nullptr) {
         auto gnssXtra = gnssHal->getExtensionXtra();
         if (!gnssXtra.isOk()) {
             ALOGD("Unable to get a handle to Xtra");
@@ -1496,7 +1353,7 @@
             agnssRilIface_V2_0 = agnssRil_V2_0;
             agnssRilIface = agnssRilIface_V2_0;
         }
-    } else {
+    } else if (gnssHal != nullptr) {
         auto agnssRil_V1_0 = gnssHal->getExtensionAGnssRil();
         if (!agnssRil_V1_0.isOk()) {
             ALOGD("Unable to get a handle to AGnssRil");
@@ -1512,7 +1369,7 @@
         } else {
             agnssIface_V2_0 = agnss_V2_0;
         }
-    } else {
+    } else if (gnssHal != nullptr) {
         auto agnss_V1_0 = gnssHal->getExtensionAGnss();
         if (!agnss_V1_0.isOk()) {
             ALOGD("Unable to get a handle to AGnss");
@@ -1521,11 +1378,21 @@
         }
     }
 
-    auto gnssNavigationMessage = gnssHal->getExtensionGnssNavigationMessage();
-    if (!gnssNavigationMessage.isOk()) {
-        ALOGD("Unable to get a handle to GnssNavigationMessage");
-    } else {
-        gnssNavigationMessageIface = gnssNavigationMessage;
+    if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
+        sp<hardware::gnss::IGnssNavigationMessageInterface> gnssNavigationMessage;
+        auto status = gnssHalAidl->getExtensionGnssNavigationMessage(&gnssNavigationMessage);
+        if (checkAidlStatus(status,
+                            "Unable to get a handle to GnssNavigationMessage AIDL interface.")) {
+            gnssNavigationMessageIface =
+                    std::make_unique<gnss::GnssNavigationMessageAidl>(gnssNavigationMessage);
+        }
+    } else if (gnssHal != nullptr) {
+        auto gnssNavigationMessage = gnssHal->getExtensionGnssNavigationMessage();
+        if (checkHidlReturn(gnssNavigationMessage,
+                            "Unable to get a handle to GnssNavigationMessage interface.")) {
+            gnssNavigationMessageIface =
+                    std::make_unique<gnss::GnssNavigationMessageHidl>(gnssNavigationMessage);
+        }
     }
 
     // Allow all causal combinations between IGnss.hal and IGnssMeasurement.hal. That means,
@@ -1563,12 +1430,12 @@
                     std::make_unique<android::gnss::GnssMeasurement_V1_1>(gnssMeasurement);
         }
     }
-    if (gnssMeasurementIface == nullptr) {
-         auto gnssMeasurement = gnssHal->getExtensionGnssMeasurement();
-         if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V1_0")) {
-             gnssMeasurementIface =
-                     std::make_unique<android::gnss::GnssMeasurement_V1_0>(gnssMeasurement);
-         }
+    if (gnssHal != nullptr && gnssMeasurementIface == nullptr) {
+        auto gnssMeasurement = gnssHal->getExtensionGnssMeasurement();
+        if (checkHidlReturn(gnssMeasurement, "Unable to get a handle to GnssMeasurement_V1_0")) {
+            gnssMeasurementIface =
+                    std::make_unique<android::gnss::GnssMeasurement_V1_0>(gnssMeasurement);
+        }
     }
 
     if (gnssHal_V2_1 != nullptr) {
@@ -1610,7 +1477,7 @@
             gnssDebugIface = gnssDebugIface_V2_0;
         }
     }
-    if (gnssDebugIface == nullptr) {
+    if (gnssHal != nullptr && gnssDebugIface == nullptr) {
         auto gnssDebug = gnssHal->getExtensionGnssDebug();
         if (!gnssDebug.isOk()) {
             ALOGD("Unable to get a handle to GnssDebug");
@@ -1619,11 +1486,13 @@
         }
     }
 
-    auto gnssNi = gnssHal->getExtensionGnssNi();
-    if (!gnssNi.isOk()) {
-        ALOGD("Unable to get a handle to GnssNi");
-    } else {
-        gnssNiIface = gnssNi;
+    if (gnssHal != nullptr) {
+        auto gnssNi = gnssHal->getExtensionGnssNi();
+        if (!gnssNi.isOk()) {
+            ALOGD("Unable to get a handle to GnssNi");
+        } else {
+            gnssNiIface = gnssNi;
+        }
     }
 
     if (gnssHalAidl != nullptr) {
@@ -1664,33 +1533,35 @@
         }
     }
 
-    auto gnssGeofencing = gnssHal->getExtensionGnssGeofencing();
-    if (!gnssGeofencing.isOk()) {
-        ALOGD("Unable to get a handle to GnssGeofencing");
-    } else {
-        gnssGeofencingIface = gnssGeofencing;
+    if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
+        sp<IGnssGeofenceAidl> gnssGeofenceAidl;
+        auto status = gnssHalAidl->getExtensionGnssGeofence(&gnssGeofenceAidl);
+        if (checkAidlStatus(status, "Unable to get a handle to GnssGeofence interface.")) {
+            gnssGeofenceAidlIface = gnssGeofenceAidl;
+        }
+    } else if (gnssHal != nullptr) {
+        auto gnssGeofencing = gnssHal->getExtensionGnssGeofencing();
+        if (checkHidlReturn(gnssGeofencing, "Unable to get a handle to GnssGeofencing")) {
+            gnssGeofencingIface = gnssGeofencing;
+        }
     }
 
     if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
-        sp<IGnssBatchingAidl> gnssBatchingAidl;
+        sp<android::hardware::gnss::IGnssBatching> gnssBatchingAidl;
         auto status = gnssHalAidl->getExtensionGnssBatching(&gnssBatchingAidl);
         if (checkAidlStatus(status, "Unable to get a handle to GnssBatching interface.")) {
-            gnssBatchingAidlIface = gnssBatchingAidl;
+            gnssBatchingIface = std::make_unique<gnss::GnssBatching>(gnssBatchingAidl);
         }
     } else if (gnssHal_V2_0 != nullptr) {
         auto gnssBatching_V2_0 = gnssHal_V2_0->getExtensionGnssBatching_2_0();
-        if (!gnssBatching_V2_0.isOk()) {
-            ALOGD("Unable to get a handle to GnssBatching_V2_0");
-        } else {
-            gnssBatchingIface_V2_0 = gnssBatching_V2_0;
+        if (checkHidlReturn(gnssBatching_V2_0, "Unable to get a handle to GnssBatching_V2_0")) {
+            gnssBatchingIface = std::make_unique<gnss::GnssBatching_V2_0>(gnssBatching_V2_0);
         }
     }
-    if (gnssBatchingIface_V2_0 == nullptr ) {
+    if (gnssHal != nullptr && gnssBatchingIface == nullptr) {
         auto gnssBatching_V1_0 = gnssHal->getExtensionGnssBatching();
-        if (!gnssBatching_V1_0.isOk()) {
-            ALOGD("Unable to get a handle to GnssBatching");
-        } else {
-            gnssBatchingIface = gnssBatching_V1_0;
+        if (checkHidlReturn(gnssBatching_V1_0, "Unable to get a handle to GnssBatching")) {
+            gnssBatchingIface = std::make_unique<gnss::GnssBatching_V1_0>(gnssBatching_V1_0);
         }
     }
 
@@ -1748,7 +1619,7 @@
     /*
      * Fail if the main interface fails to initialize
      */
-    if (gnssHal == nullptr) {
+    if (gnssHal == nullptr && gnssHalAidl == nullptr) {
         ALOGE("Unable to initialize GNSS HAL.");
         return JNI_FALSE;
     }
@@ -1763,7 +1634,7 @@
         result = gnssHal_V2_0->setCallback_2_0(gnssCbIface);
     } else if (gnssHal_V1_1 != nullptr) {
         result = gnssHal_V1_1->setCallback_1_1(gnssCbIface);
-    } else {
+    } else if (gnssHal != nullptr) {
         result = gnssHal->setCallback(gnssCbIface);
     }
 
@@ -1810,10 +1681,18 @@
     }
 
     // Set IGnssGeofencing.hal callback.
-    sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
-    if (gnssGeofencingIface != nullptr) {
+    if (gnssGeofenceAidlIface != nullptr) {
+        sp<IGnssGeofenceCallbackAidl> gnssGeofenceCallbackAidl = new GnssGeofenceCallbackAidl();
+        auto status = gnssGeofenceAidlIface->setCallback(gnssGeofenceCallbackAidl);
+        if (!checkAidlStatus(status, "IGnssGeofenceAidl setCallback() failed.")) {
+            gnssGeofenceAidlIface = nullptr;
+        }
+    } else if (gnssGeofencingIface != nullptr) {
+        sp<IGnssGeofenceCallback> gnssGeofencingCbIface = new GnssGeofenceCallback();
         auto status = gnssGeofencingIface->setCallback(gnssGeofencingCbIface);
-        checkHidlReturn(status, "IGnssGeofencing setCallback() failed.");
+        if (!checkHidlReturn(status, "IGnssGeofencing setCallback() failed.")) {
+            gnssGeofencingIface = nullptr;
+        }
     } else {
         ALOGI("Unable to initialize IGnssGeofencing interface.");
     }
@@ -1873,12 +1752,15 @@
 }
 
 static void android_location_gnss_hal_GnssNative_cleanup(JNIEnv* /* env */, jclass) {
-    if (gnssHal == nullptr) {
-        return;
+    if (gnssHalAidl != nullptr) {
+        auto status = gnssHalAidl->close();
+        checkAidlStatus(status, "IGnssAidl close() failed.");
     }
 
-    auto result = gnssHal->cleanup();
-    checkHidlReturn(result, "IGnss cleanup() failed.");
+    if (gnssHal != nullptr) {
+        auto result = gnssHal->cleanup();
+        checkHidlReturn(result, "IGnss cleanup() failed.");
+    }
 }
 
 static jboolean android_location_gnss_hal_GnssNative_set_position_mode(
@@ -2357,57 +2239,85 @@
 
 static jboolean android_location_gnss_hal_GnssNative_is_geofence_supported(JNIEnv* /* env */,
                                                                            jclass) {
-    return (gnssGeofencingIface != nullptr) ? JNI_TRUE : JNI_FALSE;
+    if (gnssGeofencingIface == nullptr && gnssGeofenceAidlIface == nullptr) {
+        return JNI_FALSE;
+    }
+    return JNI_TRUE;
 }
 
 static jboolean android_location_gnss_hal_GnssNative_add_geofence(
         JNIEnv* /* env */, jclass, jint geofenceId, jdouble latitude, jdouble longitude,
         jdouble radius, jint last_transition, jint monitor_transition,
         jint notification_responsiveness, jint unknown_timer) {
-    if (gnssGeofencingIface == nullptr) {
-        ALOGE("%s: IGnssGeofencing interface not available.", __func__);
-        return JNI_FALSE;
+    if (gnssGeofenceAidlIface != nullptr) {
+        auto status =
+                gnssGeofenceAidlIface->addGeofence(geofenceId, latitude, longitude, radius,
+                                                   last_transition, monitor_transition,
+                                                   notification_responsiveness, unknown_timer);
+        return checkAidlStatus(status, "IGnssGeofenceAidl addGeofence() failed.");
     }
 
-    auto result = gnssGeofencingIface->addGeofence(
-            geofenceId, latitude, longitude, radius,
-            static_cast<IGnssGeofenceCallback::GeofenceTransition>(last_transition),
-            monitor_transition, notification_responsiveness, unknown_timer);
-    return checkHidlReturn(result, "IGnssGeofencing addGeofence() failed.");
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface
+                              ->addGeofence(geofenceId, latitude, longitude, radius,
+                                            static_cast<IGnssGeofenceCallback::GeofenceTransition>(
+                                                    last_transition),
+                                            monitor_transition, notification_responsiveness,
+                                            unknown_timer);
+        return checkHidlReturn(result, "IGnssGeofencing addGeofence() failed.");
+    }
+
+    ALOGE("%s: IGnssGeofencing interface not available.", __func__);
+    return JNI_FALSE;
 }
 
 static jboolean android_location_gnss_hal_GnssNative_remove_geofence(JNIEnv* /* env */, jclass,
                                                                      jint geofenceId) {
-    if (gnssGeofencingIface == nullptr) {
-        ALOGE("%s: IGnssGeofencing interface not available.", __func__);
-        return JNI_FALSE;
+    if (gnssGeofenceAidlIface != nullptr) {
+        auto status = gnssGeofenceAidlIface->removeGeofence(geofenceId);
+        return checkAidlStatus(status, "IGnssGeofenceAidl removeGeofence() failed.");
     }
 
-    auto result = gnssGeofencingIface->removeGeofence(geofenceId);
-    return checkHidlReturn(result, "IGnssGeofencing removeGeofence() failed.");
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface->removeGeofence(geofenceId);
+        return checkHidlReturn(result, "IGnssGeofencing removeGeofence() failed.");
+    }
+
+    ALOGE("%s: IGnssGeofencing interface not available.", __func__);
+    return JNI_FALSE;
 }
 
 static jboolean android_location_gnss_hal_GnssNative_pause_geofence(JNIEnv* /* env */, jclass,
                                                                     jint geofenceId) {
-    if (gnssGeofencingIface == nullptr) {
-        ALOGE("%s: IGnssGeofencing interface not available.", __func__);
-        return JNI_FALSE;
+    if (gnssGeofenceAidlIface != nullptr) {
+        auto status = gnssGeofenceAidlIface->pauseGeofence(geofenceId);
+        return checkAidlStatus(status, "IGnssGeofenceAidl pauseGeofence() failed.");
     }
 
-    auto result = gnssGeofencingIface->pauseGeofence(geofenceId);
-    return checkHidlReturn(result, "IGnssGeofencing pauseGeofence() failed.");
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface->pauseGeofence(geofenceId);
+        return checkHidlReturn(result, "IGnssGeofencing pauseGeofence() failed.");
+    }
+
+    ALOGE("%s: IGnssGeofencing interface not available.", __func__);
+    return JNI_FALSE;
 }
 
 static jboolean android_location_gnss_hal_GnssNative_resume_geofence(JNIEnv* /* env */, jclass,
                                                                      jint geofenceId,
                                                                      jint monitor_transition) {
-    if (gnssGeofencingIface == nullptr) {
-        ALOGE("%s: IGnssGeofencing interface not available.", __func__);
-        return JNI_FALSE;
+    if (gnssGeofenceAidlIface != nullptr) {
+        auto status = gnssGeofenceAidlIface->resumeGeofence(geofenceId, monitor_transition);
+        return checkAidlStatus(status, "IGnssGeofenceAidl resumeGeofence() failed.");
     }
 
-    auto result = gnssGeofencingIface->resumeGeofence(geofenceId, monitor_transition);
-    return checkHidlReturn(result, "IGnssGeofencing resumeGeofence() failed.");
+    if (gnssGeofencingIface != nullptr) {
+        auto result = gnssGeofencingIface->resumeGeofence(geofenceId, monitor_transition);
+        return checkHidlReturn(result, "IGnssGeofencing resumeGeofence() failed.");
+    }
+
+    ALOGE("%s: IGnssGeofencing interface not available.", __func__);
+    return JNI_FALSE;
 }
 
 static jboolean android_location_gnss_hal_GnssNative_is_antenna_info_supported(JNIEnv* env,
@@ -2669,20 +2579,8 @@
         return JNI_FALSE;
     }
 
-    sp<IGnssNavigationMessageCallback> gnssNavigationMessageCbIface =
-            new GnssNavigationMessageCallback();
-    auto result = gnssNavigationMessageIface->setCallback(gnssNavigationMessageCbIface);
-    if (!checkHidlReturn(result, "IGnssNavigationMessage setCallback() failed.")) {
-        return JNI_FALSE;
-    }
-
-    IGnssNavigationMessage::GnssNavigationMessageStatus initRet = result;
-    if (initRet != IGnssNavigationMessage::GnssNavigationMessageStatus::SUCCESS) {
-        ALOGE("An error has been found in %s: %d", __FUNCTION__, static_cast<int32_t>(initRet));
-        return JNI_FALSE;
-    }
-
-    return JNI_TRUE;
+    return gnssNavigationMessageIface->setCallback(
+            std::make_unique<gnss::GnssNavigationMessageCallback>());
 }
 
 static jboolean android_location_gnss_hal_GnssNative_stop_navigation_message_collection(JNIEnv* env,
@@ -2691,9 +2589,7 @@
         ALOGE("%s: IGnssNavigationMessage interface not available.", __func__);
         return JNI_FALSE;
     }
-
-    auto result = gnssNavigationMessageIface->close();
-    return checkHidlReturn(result, "IGnssNavigationMessage close() failed.");
+    return gnssNavigationMessageIface->close();
 }
 
 static jboolean android_location_GnssConfiguration_set_emergency_supl_pdn(JNIEnv*,
@@ -2786,92 +2682,46 @@
 }
 
 static jint android_location_gnss_hal_GnssNative_get_batch_size(JNIEnv*) {
-    if (gnssBatchingAidlIface != nullptr) {
-        int size = 0;
-        auto status = gnssBatchingAidlIface->getBatchSize(&size);
-        if (!checkAidlStatus(status, "IGnssBatchingAidl getBatchSize() failed")) {
-            return 0;
-        }
-        return size;
-    } else if (gnssBatchingIface != nullptr) {
-        auto result = gnssBatchingIface->getBatchSize();
-        if (!checkHidlReturn(result, "IGnssBatching getBatchSize() failed.")) {
-            return 0; // failure in binder, don't support batching
-        }
-        return static_cast<jint>(result);
+    if (gnssBatchingIface == nullptr) {
+        return 0; // batching not supported, size = 0
     }
-    return 0; // batching not supported, size = 0
+    return gnssBatchingIface->getBatchSize();
 }
 
 static jboolean android_location_gnss_hal_GnssNative_init_batching(JNIEnv*, jclass) {
-    if (gnssBatchingAidlIface != nullptr) {
-        sp<IGnssBatchingCallbackAidl> gnssBatchingCbIface = new GnssBatchingCallbackAidl();
-        auto status = gnssBatchingAidlIface->init(gnssBatchingCbIface);
-        return checkAidlStatus(status, "IGnssBatchingAidl init() failed.");
-    } else if (gnssBatchingIface_V2_0 != nullptr) {
-        sp<IGnssBatchingCallback_V2_0> gnssBatchingCbIface_V2_0 = new GnssBatchingCallback_V2_0();
-        auto result = gnssBatchingIface_V2_0->init_2_0(gnssBatchingCbIface_V2_0);
-        return checkHidlReturn(result, "IGnssBatching init_2_0() failed.");
-    } else if (gnssBatchingIface != nullptr) {
-        sp<IGnssBatchingCallback_V1_0> gnssBatchingCbIface_V1_0 = new GnssBatchingCallback_V1_0();
-        auto result = gnssBatchingIface->init(gnssBatchingCbIface_V1_0);
-        return checkHidlReturn(result, "IGnssBatching init() failed.");
-    } else {
+    if (gnssBatchingIface == nullptr) {
         return JNI_FALSE; // batching not supported
     }
+    return gnssBatchingIface->init(std::make_unique<gnss::GnssBatchingCallback>());
 }
 
 static void android_location_gnss_hal_GnssNative_cleanup_batching(JNIEnv*, jclass) {
-    if (gnssBatchingAidlIface != nullptr) {
-        auto status = gnssBatchingAidlIface->cleanup();
-        checkAidlStatus(status, "IGnssBatchingAidl cleanup() failed");
-    } else if (gnssBatchingIface != nullptr) {
-        auto result = gnssBatchingIface->cleanup();
-        checkHidlReturn(result, "IGnssBatching cleanup() failed.");
+    if (gnssBatchingIface == nullptr) {
+        return; // batching not supported
     }
-    return;
+    gnssBatchingIface->cleanup();
 }
 
 static jboolean android_location_gnss_hal_GnssNative_start_batch(JNIEnv*, jclass, jlong periodNanos,
                                                                  jboolean wakeOnFifoFull) {
-    IGnssBatching_V1_0::Options options;
-    options.periodNanos = periodNanos;
-    if (wakeOnFifoFull) {
-        options.flags = static_cast<uint8_t>(IGnssBatching_V1_0::Flag::WAKEUP_ON_FIFO_FULL);
-    } else {
-        options.flags = 0;
+    if (gnssBatchingIface == nullptr) {
+        return JNI_FALSE; // batching not supported
     }
-
-    if (gnssBatchingAidlIface != nullptr) {
-        auto status = gnssBatchingAidlIface->start(periodNanos, (int)options.flags);
-        return checkAidlStatus(status, "IGnssBatchingAidl start() failed.");
-    } else if (gnssBatchingIface != nullptr) {
-        auto result = gnssBatchingIface->start(options);
-        return checkHidlReturn(result, "IGnssBatching start() failed.");
-    }
-    return JNI_FALSE; // batching not supported
+    return gnssBatchingIface->start(periodNanos, wakeOnFifoFull);
 }
 
 static void android_location_gnss_hal_GnssNative_flush_batch(JNIEnv*, jclass) {
-    if (gnssBatchingAidlIface != nullptr) {
-        auto status = gnssBatchingAidlIface->flush();
-        checkAidlStatus(status, "IGnssBatchingAidl flush() failed.");
-    } else if (gnssBatchingIface != nullptr) {
-        auto result = gnssBatchingIface->flush();
-        checkHidlReturn(result, "IGnssBatching flush() failed.");
+    if (gnssBatchingIface == nullptr) {
+        return; // batching not supported
     }
-    return;
+    gnssBatchingIface->flush();
 }
 
 static jboolean android_location_gnss_hal_GnssNative_stop_batch(JNIEnv*, jclass) {
-    if (gnssBatchingAidlIface != nullptr) {
-        auto status = gnssBatchingAidlIface->stop();
-        return checkAidlStatus(status, "IGnssBatchingAidl stop() failed.");
-    } else if (gnssBatchingIface != nullptr) {
-        auto result = gnssBatchingIface->stop();
-        return checkHidlReturn(result, "IGnssBatching stop() failed.");
+    if (gnssBatchingIface == nullptr) {
+        return JNI_FALSE; // batching not supported
     }
-    return JNI_FALSE; // batching not supported
+    return gnssBatchingIface->stop();
 }
 
 static jboolean android_location_GnssVisibilityControl_enable_nfw_location_access(
diff --git a/services/core/jni/com_android_server_net_NetworkStatsService.cpp b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
index 10b248a..5178132 100644
--- a/services/core/jni/com_android_server_net_NetworkStatsService.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsService.cpp
@@ -38,9 +38,6 @@
 
 namespace android {
 
-static const char* QTAGUID_IFACE_STATS = "/proc/net/xt_qtaguid/iface_stat_fmt";
-static const char* QTAGUID_UID_STATS = "/proc/net/xt_qtaguid/stats";
-
 // NOTE: keep these in sync with TrafficStats.java
 static const uint64_t UNKNOWN = -1;
 
@@ -72,102 +69,17 @@
     }
 }
 
-static int parseIfaceStats(const char* iface, Stats* stats) {
-    FILE *fp = fopen(QTAGUID_IFACE_STATS, "r");
-    if (fp == NULL) {
-        return -1;
-    }
-
-    char buffer[384];
-    char cur_iface[32];
-    bool foundTcp = false;
-    uint64_t rxBytes, rxPackets, txBytes, txPackets, tcpRxPackets, tcpTxPackets;
-
-    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
-        int matched = sscanf(buffer, "%31s %" SCNu64 " %" SCNu64 " %" SCNu64
-                " %" SCNu64 " " "%*u %" SCNu64 " %*u %*u %*u %*u "
-                "%*u %" SCNu64 " %*u %*u %*u %*u", cur_iface, &rxBytes,
-                &rxPackets, &txBytes, &txPackets, &tcpRxPackets, &tcpTxPackets);
-        if (matched >= 5) {
-            if (matched == 7) {
-                foundTcp = true;
-            }
-            if (!iface || !strcmp(iface, cur_iface)) {
-                stats->rxBytes += rxBytes;
-                stats->rxPackets += rxPackets;
-                stats->txBytes += txBytes;
-                stats->txPackets += txPackets;
-                if (matched == 7) {
-                    stats->tcpRxPackets += tcpRxPackets;
-                    stats->tcpTxPackets += tcpTxPackets;
-                }
-            }
-        }
-    }
-
-    if (!foundTcp) {
-        stats->tcpRxPackets = UNKNOWN;
-        stats->tcpTxPackets = UNKNOWN;
-    }
-
-    if (fclose(fp) != 0) {
-        return -1;
-    }
-    return 0;
-}
-
-static int parseUidStats(const uint32_t uid, Stats* stats) {
-    FILE *fp = fopen(QTAGUID_UID_STATS, "r");
-    if (fp == NULL) {
-        return -1;
-    }
-
-    char buffer[384];
-    char iface[32];
-    uint32_t idx, cur_uid, set;
-    uint64_t tag, rxBytes, rxPackets, txBytes, txPackets;
-
-    while (fgets(buffer, sizeof(buffer), fp) != NULL) {
-        if (sscanf(buffer,
-                "%" SCNu32 " %31s 0x%" SCNx64 " %u %u %" SCNu64 " %" SCNu64
-                " %" SCNu64 " %" SCNu64 "",
-                &idx, iface, &tag, &cur_uid, &set, &rxBytes, &rxPackets,
-                &txBytes, &txPackets) == 9) {
-            if (uid == cur_uid && tag == 0L) {
-                stats->rxBytes += rxBytes;
-                stats->rxPackets += rxPackets;
-                stats->txBytes += txBytes;
-                stats->txPackets += txPackets;
-            }
-        }
-    }
-
-    if (fclose(fp) != 0) {
-        return -1;
-    }
-    return 0;
-}
-
-static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type, jboolean useBpfStats) {
+static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
     Stats stats = {};
 
-    if (useBpfStats) {
-        if (bpfGetIfaceStats(NULL, &stats) == 0) {
-            return getStatsType(&stats, (StatsType) type);
-        } else {
-            return UNKNOWN;
-        }
-    }
-
-    if (parseIfaceStats(NULL, &stats) == 0) {
+    if (bpfGetIfaceStats(NULL, &stats) == 0) {
         return getStatsType(&stats, (StatsType) type);
     } else {
         return UNKNOWN;
     }
 }
 
-static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type,
-                          jboolean useBpfStats) {
+static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
     ScopedUtfChars iface8(env, iface);
     if (iface8.c_str() == NULL) {
         return UNKNOWN;
@@ -175,33 +87,17 @@
 
     Stats stats = {};
 
-    if (useBpfStats) {
-        if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
-            return getStatsType(&stats, (StatsType) type);
-        } else {
-            return UNKNOWN;
-        }
-    }
-
-    if (parseIfaceStats(iface8.c_str(), &stats) == 0) {
+    if (bpfGetIfaceStats(iface8.c_str(), &stats) == 0) {
         return getStatsType(&stats, (StatsType) type);
     } else {
         return UNKNOWN;
     }
 }
 
-static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type, jboolean useBpfStats) {
+static jlong getUidStat(JNIEnv* env, jclass clazz, jint uid, jint type) {
     Stats stats = {};
 
-    if (useBpfStats) {
-        if (bpfGetUidStats(uid, &stats) == 0) {
-            return getStatsType(&stats, (StatsType) type);
-        } else {
-            return UNKNOWN;
-        }
-    }
-
-    if (parseUidStats(uid, &stats) == 0) {
+    if (bpfGetUidStats(uid, &stats) == 0) {
         return getStatsType(&stats, (StatsType) type);
     } else {
         return UNKNOWN;
@@ -209,9 +105,9 @@
 }
 
 static const JNINativeMethod gMethods[] = {
-    {"nativeGetTotalStat", "(IZ)J", (void*) getTotalStat},
-    {"nativeGetIfaceStat", "(Ljava/lang/String;IZ)J", (void*) getIfaceStat},
-    {"nativeGetUidStat", "(IIZ)J", (void*) getUidStat},
+        {"nativeGetTotalStat", "(I)J", (void*)getTotalStat},
+        {"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*)getIfaceStat},
+        {"nativeGetUidStat", "(II)J", (void*)getUidStat},
 };
 
 int register_android_server_net_NetworkStatsService(JNIEnv* env) {
diff --git a/services/core/jni/gnss/Android.bp b/services/core/jni/gnss/Android.bp
index 9085fa7..6c6b304 100644
--- a/services/core/jni/gnss/Android.bp
+++ b/services/core/jni/gnss/Android.bp
@@ -24,9 +24,13 @@
 
     srcs: [
         "GnssAntennaInfoCallback.cpp",
+        "GnssBatching.cpp",
+        "GnssBatchingCallback.cpp",
         "GnssConfiguration.cpp",
         "GnssMeasurement.cpp",
         "GnssMeasurementCallback.cpp",
+        "GnssNavigationMessage.cpp",
+        "GnssNavigationMessageCallback.cpp",
         "Utils.cpp",
     ],
 }
diff --git a/services/core/jni/gnss/GnssBatching.cpp b/services/core/jni/gnss/GnssBatching.cpp
new file mode 100644
index 0000000..b66bf21
--- /dev/null
+++ b/services/core/jni/gnss/GnssBatching.cpp
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Define LOG_TAG before <log/log.h> to overwrite the default value.
+#define LOG_TAG "GnssBatchingJni"
+
+#include "GnssBatching.h"
+
+#include "Utils.h"
+
+using android::hardware::gnss::IGnssBatching;
+using IGnssBatching_V1_0 = android::hardware::gnss::V1_0::IGnssBatching;
+using IGnssBatching_V2_0 = android::hardware::gnss::V2_0::IGnssBatching;
+
+namespace android::gnss {
+
+// Implementation of GnssBatching (AIDL HAL)
+
+GnssBatching::GnssBatching(const sp<IGnssBatching>& iGnssBatching) : mIGnssBatching(iGnssBatching) {
+    assert(mIGnssBatching != nullptr);
+}
+
+jboolean GnssBatching::init(const std::unique_ptr<GnssBatchingCallback>& callback) {
+    auto status = mIGnssBatching->init(callback->getAidl());
+    return checkAidlStatus(status, "IGnssBatchingAidl init() failed.");
+}
+
+jint GnssBatching::getBatchSize() {
+    int size = 0;
+    auto status = mIGnssBatching->getBatchSize(&size);
+    if (!checkAidlStatus(status, "IGnssBatchingAidl getBatchSize() failed")) {
+        return 0;
+    }
+    return size;
+}
+
+jboolean GnssBatching::start(long periodNanos, bool wakeOnFifoFull) {
+    int flags = (wakeOnFifoFull) ? IGnssBatching::WAKEUP_ON_FIFO_FULL : 0;
+    auto status = mIGnssBatching->start(periodNanos, flags);
+    return checkAidlStatus(status, "IGnssBatchingAidl start() failed.");
+}
+
+jboolean GnssBatching::stop() {
+    auto status = mIGnssBatching->stop();
+    return checkAidlStatus(status, "IGnssBatchingAidl stop() failed.");
+}
+
+jboolean GnssBatching::flush() {
+    auto status = mIGnssBatching->flush();
+    return checkAidlStatus(status, "IGnssBatchingAidl flush() failed.");
+}
+
+jboolean GnssBatching::cleanup() {
+    auto status = mIGnssBatching->cleanup();
+    return checkAidlStatus(status, "IGnssBatchingAidl cleanup() failed");
+}
+
+// Implementation of GnssBatching_V1_0
+
+GnssBatching_V1_0::GnssBatching_V1_0(const sp<IGnssBatching_V1_0>& iGnssBatching)
+      : mIGnssBatching_V1_0(iGnssBatching) {
+    assert(mIGnssBatching_V1_0 != nullptr);
+}
+
+jboolean GnssBatching_V1_0::init(const std::unique_ptr<GnssBatchingCallback>& callback) {
+    auto result = mIGnssBatching_V1_0->init(callback->getV1_0());
+    return checkHidlReturn(result, "IGnssBatching_V1_0 init() failed.");
+}
+
+jint GnssBatching_V1_0::getBatchSize() {
+    auto result = mIGnssBatching_V1_0->getBatchSize();
+    if (!checkHidlReturn(result, "IGnssBatching getBatchSize() failed.")) {
+        return 0; // failure in binder, don't support batching
+    }
+    return static_cast<jint>(result);
+}
+
+jboolean GnssBatching_V1_0::start(long periodNanos, bool wakeOnFifoFull) {
+    IGnssBatching_V1_0::Options options;
+    options.periodNanos = periodNanos;
+    if (wakeOnFifoFull) {
+        options.flags = static_cast<uint8_t>(IGnssBatching_V1_0::Flag::WAKEUP_ON_FIFO_FULL);
+    } else {
+        options.flags = 0;
+    }
+
+    auto result = mIGnssBatching_V1_0->start(options);
+    return checkHidlReturn(result, "IGnssBatching start() failed.");
+}
+
+jboolean GnssBatching_V1_0::stop() {
+    auto result = mIGnssBatching_V1_0->stop();
+    return checkHidlReturn(result, "IGnssBatching stop() failed.");
+}
+
+jboolean GnssBatching_V1_0::flush() {
+    auto result = mIGnssBatching_V1_0->flush();
+    return checkHidlReturn(result, "IGnssBatching flush() failed.");
+}
+
+jboolean GnssBatching_V1_0::cleanup() {
+    auto result = mIGnssBatching_V1_0->cleanup();
+    return checkHidlReturn(result, "IGnssBatching cleanup() failed.");
+}
+
+// Implementation of GnssBatching_V2_0
+
+GnssBatching_V2_0::GnssBatching_V2_0(const sp<IGnssBatching_V2_0>& iGnssBatching)
+      : GnssBatching_V1_0{iGnssBatching}, mIGnssBatching_V2_0(iGnssBatching) {
+    assert(mIGnssBatching_V2_0 != nullptr);
+}
+
+jboolean GnssBatching_V2_0::init(const std::unique_ptr<GnssBatchingCallback>& callback) {
+    auto result = mIGnssBatching_V2_0->init_2_0(callback->getV2_0());
+    return checkHidlReturn(result, "IGnssBatching_V2_0 init() failed.");
+}
+
+} // namespace android::gnss
diff --git a/services/core/jni/gnss/GnssBatching.h b/services/core/jni/gnss/GnssBatching.h
new file mode 100644
index 0000000..a98ca9b
--- /dev/null
+++ b/services/core/jni/gnss/GnssBatching.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#ifndef _ANDROID_SERVER_GNSS_GNSSBATCHING_H
+#define _ANDROID_SERVER_GNSS_GNSSBATCHING_H
+
+#pragma once
+
+#ifndef LOG_TAG
+#error LOG_TAG must be defined before including this file.
+#endif
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <android/hardware/gnss/BnGnssBatching.h>
+#include <log/log.h>
+
+#include "GnssBatchingCallback.h"
+#include "jni.h"
+
+namespace android::gnss {
+
+class GnssBatchingInterface {
+public:
+    virtual ~GnssBatchingInterface() {}
+    virtual jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) = 0;
+    virtual jint getBatchSize() = 0;
+    virtual jboolean start(long periodNanos, bool wakeupOnFifoFull) = 0;
+    virtual jboolean stop() = 0;
+    virtual jboolean flush() = 0;
+    virtual jboolean cleanup() = 0;
+};
+
+class GnssBatching : public GnssBatchingInterface {
+public:
+    GnssBatching(const sp<android::hardware::gnss::IGnssBatching>& iGnssBatching);
+    jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) override;
+    jint getBatchSize() override;
+    jboolean start(long periodNanos, bool wakeupOnFifoFull) override;
+    jboolean stop() override;
+    jboolean flush() override;
+    jboolean cleanup() override;
+
+private:
+    const sp<android::hardware::gnss::IGnssBatching> mIGnssBatching;
+};
+
+class GnssBatching_V1_0 : public GnssBatchingInterface {
+public:
+    GnssBatching_V1_0(const sp<android::hardware::gnss::V1_0::IGnssBatching>& iGnssBatching);
+    jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) override;
+    jint getBatchSize() override;
+    jboolean start(long periodNanos, bool wakeupOnFifoFull) override;
+    jboolean stop() override;
+    jboolean flush() override;
+    jboolean cleanup() override;
+
+private:
+    const sp<android::hardware::gnss::V1_0::IGnssBatching> mIGnssBatching_V1_0;
+};
+
+class GnssBatching_V2_0 : public GnssBatching_V1_0 {
+public:
+    GnssBatching_V2_0(const sp<android::hardware::gnss::V2_0::IGnssBatching>& iGnssBatching);
+    jboolean init(const std::unique_ptr<GnssBatchingCallback>& callback) override;
+
+private:
+    const sp<android::hardware::gnss::V2_0::IGnssBatching> mIGnssBatching_V2_0;
+};
+
+} // namespace android::gnss
+
+#endif // _ANDROID_SERVER_GNSS_GNSSBATCHING_H
diff --git a/services/core/jni/gnss/GnssBatchingCallback.cpp b/services/core/jni/gnss/GnssBatchingCallback.cpp
new file mode 100644
index 0000000..d2a5547
--- /dev/null
+++ b/services/core/jni/gnss/GnssBatchingCallback.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssBatchingCbJni"
+
+#include "GnssBatchingCallback.h"
+
+namespace android::gnss {
+
+namespace {
+
+jmethodID method_reportLocationBatch;
+
+} // anonymous namespace
+
+using android::hardware::hidl_vec;
+using binder::Status;
+using hardware::Return;
+
+using GnssLocationAidl = android::hardware::gnss::GnssLocation;
+using GnssLocation_V1_0 = android::hardware::gnss::V1_0::GnssLocation;
+using GnssLocation_V2_0 = android::hardware::gnss::V2_0::GnssLocation;
+
+void GnssBatching_class_init_once(JNIEnv* env, jclass clazz) {
+    method_reportLocationBatch =
+            env->GetMethodID(clazz, "reportLocationBatch", "([Landroid/location/Location;)V");
+}
+
+Status GnssBatchingCallbackAidl::gnssLocationBatchCb(
+        const std::vector<android::hardware::gnss::GnssLocation>& locations) {
+    GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(hidl_vec<GnssLocationAidl>(locations));
+    return Status::ok();
+}
+
+Return<void> GnssBatchingCallback_V1_0::gnssLocationBatchCb(
+        const hidl_vec<GnssLocation_V1_0>& locations) {
+    return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations);
+}
+
+Return<void> GnssBatchingCallback_V2_0::gnssLocationBatchCb(
+        const hidl_vec<GnssLocation_V2_0>& locations) {
+    return GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(locations);
+}
+
+} // namespace android::gnss
diff --git a/services/core/jni/gnss/GnssBatchingCallback.h b/services/core/jni/gnss/GnssBatchingCallback.h
new file mode 100644
index 0000000..a9dd4304
--- /dev/null
+++ b/services/core/jni/gnss/GnssBatchingCallback.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#ifndef _ANDROID_SERVER_GNSS_GNSSBATCHCALLBACK_H
+#define _ANDROID_SERVER_GNSS_GNSSBATCHCALLBACK_H
+
+#pragma once
+
+#ifndef LOG_TAG
+#error LOG_TAG must be defined before including this file.
+#endif
+
+#include <android/hardware/gnss/1.0/IGnssBatching.h>
+#include <android/hardware/gnss/2.0/IGnssBatching.h>
+#include <android/hardware/gnss/BnGnssBatchingCallback.h>
+#include <log/log.h>
+
+#include <vector>
+
+#include "Utils.h"
+#include "jni.h"
+
+namespace android::gnss {
+
+namespace {
+
+extern jmethodID method_reportLocationBatch;
+
+} // anonymous namespace
+
+void GnssBatching_class_init_once(JNIEnv* env, jclass clazz);
+
+class GnssBatchingCallbackAidl : public hardware::gnss::BnGnssBatchingCallback {
+public:
+    GnssBatchingCallbackAidl() {}
+    android::binder::Status gnssLocationBatchCb(
+            const std::vector<android::hardware::gnss::GnssLocation>& locations) override;
+};
+
+class GnssBatchingCallback_V1_0 : public hardware::gnss::V1_0::IGnssBatchingCallback {
+public:
+    GnssBatchingCallback_V1_0() {}
+    hardware::Return<void> gnssLocationBatchCb(
+            const hardware::hidl_vec<hardware::gnss::V1_0::GnssLocation>& locations) override;
+};
+
+class GnssBatchingCallback_V2_0 : public hardware::gnss::V2_0::IGnssBatchingCallback {
+public:
+    GnssBatchingCallback_V2_0() {}
+    hardware::Return<void> gnssLocationBatchCb(
+            const hardware::hidl_vec<hardware::gnss::V2_0::GnssLocation>& locations) override;
+};
+
+class GnssBatchingCallback {
+public:
+    GnssBatchingCallback() {}
+    sp<GnssBatchingCallbackAidl> getAidl() {
+        if (callbackAidl == nullptr) {
+            callbackAidl = sp<GnssBatchingCallbackAidl>::make();
+        }
+        return callbackAidl;
+    }
+
+    sp<GnssBatchingCallback_V1_0> getV1_0() {
+        if (callbackV1_0 == nullptr) {
+            callbackV1_0 = sp<GnssBatchingCallback_V1_0>::make();
+        }
+        return callbackV1_0;
+    }
+
+    sp<GnssBatchingCallback_V2_0> getV2_0() {
+        if (callbackV2_0 == nullptr) {
+            callbackV2_0 = sp<GnssBatchingCallback_V2_0>::make();
+        }
+        return callbackV2_0;
+    }
+
+private:
+    sp<GnssBatchingCallbackAidl> callbackAidl;
+    sp<GnssBatchingCallback_V1_0> callbackV1_0;
+    sp<GnssBatchingCallback_V2_0> callbackV2_0;
+};
+
+struct GnssBatchingCallbackUtil {
+    template <class T>
+    static hardware::Return<void> gnssLocationBatchCbImpl(const hardware::hidl_vec<T>& locations);
+
+private:
+    GnssBatchingCallbackUtil() = delete;
+};
+
+template <class T>
+hardware::Return<void> GnssBatchingCallbackUtil::gnssLocationBatchCbImpl(
+        const hardware::hidl_vec<T>& locations) {
+    JNIEnv* env = getJniEnv();
+
+    jobjectArray jLocations = env->NewObjectArray(locations.size(), class_location, nullptr);
+
+    for (uint16_t i = 0; i < locations.size(); ++i) {
+        jobject jLocation = translateGnssLocation(env, locations[i]);
+        env->SetObjectArrayElement(jLocations, i, jLocation);
+        env->DeleteLocalRef(jLocation);
+    }
+
+    env->CallVoidMethod(android::getCallbacksObj(), method_reportLocationBatch, jLocations);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+
+    env->DeleteLocalRef(jLocations);
+
+    return hardware::Void();
+}
+
+} // namespace android::gnss
+
+#endif // _ANDROID_SERVER_GNSS_GNSSBATCHCALLBACK_H
\ No newline at end of file
diff --git a/services/core/jni/gnss/GnssNavigationMessage.cpp b/services/core/jni/gnss/GnssNavigationMessage.cpp
new file mode 100644
index 0000000..75aee74
--- /dev/null
+++ b/services/core/jni/gnss/GnssNavigationMessage.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Define LOG_TAG before <log/log.h> to overwrite the default value.
+#define LOG_TAG "GnssNavigationMessageJni"
+
+#include "GnssNavigationMessage.h"
+
+#include "Utils.h"
+
+namespace android::gnss {
+
+using hardware::gnss::IGnssNavigationMessageInterface;
+using IGnssNavigationMessageHidl = hardware::gnss::V1_0::IGnssNavigationMessage;
+
+// Implementation of GnssNavigationMessage (AIDL HAL)
+
+GnssNavigationMessageAidl::GnssNavigationMessageAidl(
+        const sp<IGnssNavigationMessageInterface>& iGnssNavigationMessage)
+      : mIGnssNavigationMessage(iGnssNavigationMessage) {
+    assert(mIGnssNavigationMessage != nullptr);
+}
+
+jboolean GnssNavigationMessageAidl::setCallback(
+        const std::unique_ptr<GnssNavigationMessageCallback>& callback) {
+    auto status = mIGnssNavigationMessage->setCallback(callback->getAidl());
+    return checkAidlStatus(status, "IGnssNavigationMessageAidl setCallback() failed.");
+}
+
+jboolean GnssNavigationMessageAidl::close() {
+    auto status = mIGnssNavigationMessage->close();
+    return checkAidlStatus(status, "IGnssNavigationMessageAidl close() failed");
+}
+
+// Implementation of GnssNavigationMessageHidl
+
+GnssNavigationMessageHidl::GnssNavigationMessageHidl(
+        const sp<IGnssNavigationMessageHidl>& iGnssNavigationMessage)
+      : mIGnssNavigationMessageHidl(iGnssNavigationMessage) {
+    assert(mIGnssNavigationMessageHidl != nullptr);
+}
+
+jboolean GnssNavigationMessageHidl::setCallback(
+        const std::unique_ptr<GnssNavigationMessageCallback>& callback) {
+    auto result = mIGnssNavigationMessageHidl->setCallback(callback->getHidl());
+
+    IGnssNavigationMessageHidl::GnssNavigationMessageStatus initRet = result;
+    if (initRet != IGnssNavigationMessageHidl::GnssNavigationMessageStatus::SUCCESS) {
+        ALOGE("An error has been found in %s: %d", __FUNCTION__, static_cast<int32_t>(initRet));
+        return JNI_FALSE;
+    }
+    return JNI_TRUE;
+}
+
+jboolean GnssNavigationMessageHidl::close() {
+    auto result = mIGnssNavigationMessageHidl->close();
+    return checkHidlReturn(result, "IGnssNavigationMessage close() failed.");
+}
+
+} // namespace android::gnss
diff --git a/services/core/jni/gnss/GnssNavigationMessage.h b/services/core/jni/gnss/GnssNavigationMessage.h
new file mode 100644
index 0000000..e3a1e4a
--- /dev/null
+++ b/services/core/jni/gnss/GnssNavigationMessage.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#ifndef _ANDROID_SERVER_GNSS_GNSSNAVIGATIONMESSAGE_H
+#define _ANDROID_SERVER_GNSS_GNSSNAVIGATIONMESSAGE_H
+
+#pragma once
+
+#ifndef LOG_TAG
+#error LOG_TAG must be defined before including this file.
+#endif
+
+#include <android/hardware/gnss/1.0/IGnssNavigationMessage.h>
+#include <android/hardware/gnss/BnGnssNavigationMessageInterface.h>
+#include <log/log.h>
+
+#include "GnssNavigationMessageCallback.h"
+#include "jni.h"
+
+namespace android::gnss {
+
+class GnssNavigationMessageInterface {
+public:
+    virtual ~GnssNavigationMessageInterface() {}
+    virtual jboolean setCallback(
+            const std::unique_ptr<GnssNavigationMessageCallback>& callback) = 0;
+    virtual jboolean close() = 0;
+};
+
+class GnssNavigationMessageAidl : public GnssNavigationMessageInterface {
+public:
+    GnssNavigationMessageAidl(const sp<android::hardware::gnss::IGnssNavigationMessageInterface>&
+                                      iGnssNavigationMessage);
+    jboolean setCallback(const std::unique_ptr<GnssNavigationMessageCallback>& callback) override;
+    jboolean close() override;
+
+private:
+    const sp<android::hardware::gnss::IGnssNavigationMessageInterface> mIGnssNavigationMessage;
+};
+
+class GnssNavigationMessageHidl : public GnssNavigationMessageInterface {
+public:
+    GnssNavigationMessageHidl(const sp<android::hardware::gnss::V1_0::IGnssNavigationMessage>&
+                                      iGnssNavigationMessage);
+    jboolean setCallback(const std::unique_ptr<GnssNavigationMessageCallback>& callback) override;
+    jboolean close() override;
+
+private:
+    const sp<android::hardware::gnss::V1_0::IGnssNavigationMessage> mIGnssNavigationMessageHidl;
+};
+
+} // namespace android::gnss
+
+#endif // _ANDROID_SERVER_GNSS_GNSSNAVIGATIONMESSAGE_H
diff --git a/services/core/jni/gnss/GnssNavigationMessageCallback.cpp b/services/core/jni/gnss/GnssNavigationMessageCallback.cpp
new file mode 100644
index 0000000..1779c95
--- /dev/null
+++ b/services/core/jni/gnss/GnssNavigationMessageCallback.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GnssNavMsgCbJni"
+
+#include "GnssNavigationMessageCallback.h"
+
+namespace android::gnss {
+
+namespace {
+
+jclass class_gnssNavigationMessage;
+jmethodID method_reportNavigationMessages;
+jmethodID method_gnssNavigationMessageCtor;
+
+} // anonymous namespace
+
+using binder::Status;
+using hardware::Return;
+using hardware::Void;
+
+using GnssNavigationMessageAidl =
+        android::hardware::gnss::IGnssNavigationMessageCallback::GnssNavigationMessage;
+using GnssNavigationMessageHidl =
+        android::hardware::gnss::V1_0::IGnssNavigationMessageCallback::GnssNavigationMessage;
+
+void GnssNavigationMessage_class_init_once(JNIEnv* env, jclass clazz) {
+    method_reportNavigationMessages =
+            env->GetMethodID(clazz, "reportNavigationMessage",
+                             "(Landroid/location/GnssNavigationMessage;)V");
+
+    jclass gnssNavigationMessageClass = env->FindClass("android/location/GnssNavigationMessage");
+    class_gnssNavigationMessage = (jclass)env->NewGlobalRef(gnssNavigationMessageClass);
+    method_gnssNavigationMessageCtor =
+            env->GetMethodID(class_gnssNavigationMessage, "<init>", "()V");
+}
+
+Status GnssNavigationMessageCallbackAidl::gnssNavigationMessageCb(
+        const GnssNavigationMessageAidl& message) {
+    GnssNavigationMessageCallbackUtil::gnssNavigationMessageCbImpl(message);
+    return Status::ok();
+}
+
+Return<void> GnssNavigationMessageCallbackHidl::gnssNavigationMessageCb(
+        const GnssNavigationMessageHidl& message) {
+    GnssNavigationMessageCallbackUtil::gnssNavigationMessageCbImpl(message);
+    return Void();
+}
+
+} // namespace android::gnss
diff --git a/services/core/jni/gnss/GnssNavigationMessageCallback.h b/services/core/jni/gnss/GnssNavigationMessageCallback.h
new file mode 100644
index 0000000..fe76fc7
--- /dev/null
+++ b/services/core/jni/gnss/GnssNavigationMessageCallback.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#ifndef _ANDROID_SERVER_GNSS_GNSSNAVIGATIONMESSAGECALLBACK_H
+#define _ANDROID_SERVER_GNSS_GNSSNAVIGATIONMESSAGECALLBACK_H
+
+#pragma once
+
+#ifndef LOG_TAG
+#error LOG_TAG must be defined before including this file.
+#endif
+
+#include <android/hardware/gnss/1.0/IGnssNavigationMessage.h>
+#include <android/hardware/gnss/BnGnssNavigationMessageCallback.h>
+#include <log/log.h>
+
+#include <vector>
+
+#include "Utils.h"
+#include "jni.h"
+
+namespace android::gnss {
+
+namespace {
+
+extern jclass class_gnssNavigationMessage;
+extern jmethodID method_reportNavigationMessages;
+extern jmethodID method_gnssNavigationMessageCtor;
+
+} // anonymous namespace
+
+void GnssNavigationMessage_class_init_once(JNIEnv* env, jclass clazz);
+
+class GnssNavigationMessageCallbackAidl : public hardware::gnss::BnGnssNavigationMessageCallback {
+public:
+    GnssNavigationMessageCallbackAidl() {}
+    android::binder::Status gnssNavigationMessageCb(
+            const hardware::gnss::IGnssNavigationMessageCallback::GnssNavigationMessage& message)
+            override;
+};
+
+class GnssNavigationMessageCallbackHidl
+      : public hardware::gnss::V1_0::IGnssNavigationMessageCallback {
+public:
+    GnssNavigationMessageCallbackHidl() {}
+
+    hardware::Return<void> gnssNavigationMessageCb(
+            const hardware::gnss::V1_0::IGnssNavigationMessageCallback::GnssNavigationMessage&
+                    message) override;
+};
+
+class GnssNavigationMessageCallback {
+public:
+    GnssNavigationMessageCallback() {}
+    sp<GnssNavigationMessageCallbackAidl> getAidl() {
+        if (callbackAidl == nullptr) {
+            callbackAidl = sp<GnssNavigationMessageCallbackAidl>::make();
+        }
+        return callbackAidl;
+    }
+
+    sp<GnssNavigationMessageCallbackHidl> getHidl() {
+        if (callbackHidl == nullptr) {
+            callbackHidl = sp<GnssNavigationMessageCallbackHidl>::make();
+        }
+        return callbackHidl;
+    }
+
+private:
+    sp<GnssNavigationMessageCallbackAidl> callbackAidl;
+    sp<GnssNavigationMessageCallbackHidl> callbackHidl;
+};
+
+struct GnssNavigationMessageCallbackUtil {
+    template <class T>
+    static void gnssNavigationMessageCbImpl(const T& message);
+
+private:
+    GnssNavigationMessageCallbackUtil() = delete;
+};
+
+template <class T>
+void GnssNavigationMessageCallbackUtil::gnssNavigationMessageCbImpl(const T& message) {
+    JNIEnv* env = getJniEnv();
+
+    size_t dataLength = message.data.size();
+
+    std::vector<uint8_t> navigationData = message.data;
+    uint8_t* data = &(navigationData[0]);
+    if (dataLength == 0 || data == nullptr) {
+        ALOGE("Invalid Navigation Message found: data=%p, length=%zd", data, dataLength);
+        return;
+    }
+
+    JavaObject object(env, class_gnssNavigationMessage, method_gnssNavigationMessageCtor);
+    SET(Type, static_cast<int32_t>(message.type));
+    SET(Svid, static_cast<int32_t>(message.svid));
+    SET(MessageId, static_cast<int32_t>(message.messageId));
+    SET(SubmessageId, static_cast<int32_t>(message.submessageId));
+    object.callSetter("setData", data, dataLength);
+    SET(Status, static_cast<int32_t>(message.status));
+
+    jobject navigationMessage = object.get();
+    env->CallVoidMethod(mCallbacksObj, method_reportNavigationMessages, navigationMessage);
+    checkAndClearExceptionFromCallback(env, __FUNCTION__);
+    env->DeleteLocalRef(navigationMessage);
+    return;
+}
+
+} // namespace android::gnss
+
+#endif // _ANDROID_SERVER_GNSS_GNSSNAVIGATIONMESSAGECALLBACK_H
\ No newline at end of file
diff --git a/services/core/jni/gnss/Utils.cpp b/services/core/jni/gnss/Utils.cpp
index 8cbdfb8..40a94ce 100644
--- a/services/core/jni/gnss/Utils.cpp
+++ b/services/core/jni/gnss/Utils.cpp
@@ -18,6 +18,9 @@
 
 #include "Utils.h"
 
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <android/hardware/gnss/2.0/IGnss.h>
+#include <utils/SystemClock.h>
 /*
  * Save a pointer to JavaVm to attach/detach threads executing
  * callback methods that need to make JNI calls.
@@ -29,9 +32,29 @@
 namespace {
 
 thread_local std::unique_ptr<ScopedJniThreadAttach> tJniThreadAttacher;
+jmethodID method_locationCtor;
 
 } // anonymous namespace
 
+jclass class_location;
+
+namespace gnss {
+void Utils_class_init_once(JNIEnv* env) {
+    jclass locationClass = env->FindClass("android/location/Location");
+    class_location = (jclass)env->NewGlobalRef(locationClass);
+    method_locationCtor = env->GetMethodID(class_location, "<init>", "(Ljava/lang/String;)V");
+}
+} // namespace gnss
+
+jobject mCallbacksObj = nullptr;
+
+jobject& getCallbacksObj() {
+    return mCallbacksObj;
+}
+
+using GnssLocation_V1_0 = android::hardware::gnss::V1_0::GnssLocation;
+using GnssLocation_V2_0 = android::hardware::gnss::V2_0::GnssLocation;
+
 // Define Java method signatures for all known types.
 template <>
 const char* const JavaMethodHelper<uint8_t>::signature_ = "(B)V";
@@ -130,4 +153,103 @@
     return env;
 }
 
+template <>
+jobject translateGnssLocation(JNIEnv* env, const android::hardware::gnss::GnssLocation& location) {
+    JavaObject object(env, class_location, method_locationCtor, "gps");
+
+    uint32_t flags = static_cast<uint32_t>(location.gnssLocationFlags);
+    if (flags & android::hardware::gnss::GnssLocation::HAS_LAT_LONG) {
+        SET(Latitude, location.latitudeDegrees);
+        SET(Longitude, location.longitudeDegrees);
+    }
+    if (flags & android::hardware::gnss::GnssLocation::HAS_ALTITUDE) {
+        SET(Altitude, location.altitudeMeters);
+    }
+    if (flags & android::hardware::gnss::GnssLocation::HAS_SPEED) {
+        SET(Speed, (float)location.speedMetersPerSec);
+    }
+    if (flags & android::hardware::gnss::GnssLocation::HAS_BEARING) {
+        SET(Bearing, (float)location.bearingDegrees);
+    }
+    if (flags & android::hardware::gnss::GnssLocation::HAS_HORIZONTAL_ACCURACY) {
+        SET(Accuracy, (float)location.horizontalAccuracyMeters);
+    }
+    if (flags & android::hardware::gnss::GnssLocation::HAS_VERTICAL_ACCURACY) {
+        SET(VerticalAccuracyMeters, (float)location.verticalAccuracyMeters);
+    }
+    if (flags & android::hardware::gnss::GnssLocation::HAS_SPEED_ACCURACY) {
+        SET(SpeedAccuracyMetersPerSecond, (float)location.speedAccuracyMetersPerSecond);
+    }
+    if (flags & android::hardware::gnss::GnssLocation::HAS_BEARING_ACCURACY) {
+        SET(BearingAccuracyDegrees, (float)location.bearingAccuracyDegrees);
+    }
+    SET(Time, location.timestampMillis);
+
+    flags = static_cast<uint32_t>(location.elapsedRealtime.flags);
+    if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIMESTAMP_NS) {
+        SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs);
+    }
+    if (flags & android::hardware::gnss::ElapsedRealtime::HAS_TIME_UNCERTAINTY_NS) {
+        SET(ElapsedRealtimeUncertaintyNanos,
+            static_cast<double>(location.elapsedRealtime.timeUncertaintyNs));
+    }
+
+    return object.get();
+}
+
+template <>
+jobject translateGnssLocation(JNIEnv* env, const GnssLocation_V1_0& location) {
+    JavaObject object(env, class_location, method_locationCtor, "gps");
+
+    uint16_t flags = static_cast<uint16_t>(location.gnssLocationFlags);
+    if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_LAT_LONG) {
+        SET(Latitude, location.latitudeDegrees);
+        SET(Longitude, location.longitudeDegrees);
+    }
+    if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_ALTITUDE) {
+        SET(Altitude, location.altitudeMeters);
+    }
+    if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED) {
+        SET(Speed, location.speedMetersPerSec);
+    }
+    if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING) {
+        SET(Bearing, location.bearingDegrees);
+    }
+    if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_HORIZONTAL_ACCURACY) {
+        SET(Accuracy, location.horizontalAccuracyMeters);
+    }
+    if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+        SET(VerticalAccuracyMeters, location.verticalAccuracyMeters);
+    }
+    if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_SPEED_ACCURACY) {
+        SET(SpeedAccuracyMetersPerSecond, location.speedAccuracyMetersPerSecond);
+    }
+    if (flags & android::hardware::gnss::V1_0::GnssLocationFlags::HAS_BEARING_ACCURACY) {
+        SET(BearingAccuracyDegrees, location.bearingAccuracyDegrees);
+    }
+    SET(Time, location.timestamp);
+    SET(ElapsedRealtimeNanos, android::elapsedRealtimeNano());
+
+    return object.get();
+}
+
+template <>
+jobject translateGnssLocation(JNIEnv* env, const GnssLocation_V2_0& location) {
+    JavaObject object(env, class_location, translateGnssLocation(env, location.v1_0));
+
+    const uint16_t flags = static_cast<uint16_t>(location.elapsedRealtime.flags);
+
+    // Overwrite ElapsedRealtimeNanos when available from HAL.
+    if (flags & android::hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS) {
+        SET(ElapsedRealtimeNanos, location.elapsedRealtime.timestampNs);
+    }
+
+    if (flags & android::hardware::gnss::V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS) {
+        SET(ElapsedRealtimeUncertaintyNanos,
+            static_cast<double>(location.elapsedRealtime.timeUncertaintyNs));
+    }
+
+    return object.get();
+}
+
 } // namespace android
diff --git a/services/core/jni/gnss/Utils.h b/services/core/jni/gnss/Utils.h
index 0938a1b..1bd69c4 100644
--- a/services/core/jni/gnss/Utils.h
+++ b/services/core/jni/gnss/Utils.h
@@ -37,11 +37,19 @@
 
 // Must match the value from GnssMeasurement.java
 const uint32_t ADR_STATE_HALF_CYCLE_REPORTED = (1 << 4);
+extern jmethodID method_locationCtor;
 
 } // anonymous namespace
 
+extern jclass class_location;
 extern jobject mCallbacksObj;
 
+namespace gnss {
+void Utils_class_init_once(JNIEnv* env);
+} // namespace gnss
+
+jobject& getCallbacksObj();
+
 jboolean checkHidlReturn(hardware::Return<bool>& result, const char* errorMessage);
 
 jboolean checkAidlStatus(const android::binder::Status& status, const char* errorMessage);
@@ -190,6 +198,9 @@
 
 JNIEnv* getJniEnv();
 
+template <class T>
+jobject translateGnssLocation(JNIEnv* env, const T& location);
+
 } // namespace android
 
 #endif // _ANDROID_SERVER_GNSS_UTILS_H
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index 429edf1..2f4dd57 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -26,6 +26,10 @@
     <xs:element name="displayConfiguration">
         <xs:complexType>
             <xs:sequence>
+                <xs:element type="densityMap" name="densityMap" minOccurs="0" maxOccurs="1">
+                    <xs:annotation name="nullable"/>
+                    <xs:annotation name="final"/>
+                </xs:element>
                 <xs:element type="nitsMap" name="screenBrightnessMap">
                     <xs:annotation name="nonnull"/>
                     <xs:annotation name="final"/>
@@ -181,5 +185,27 @@
         </xs:sequence>
     </xs:complexType>
 
+    <xs:complexType name="densityMap">
+        <xs:sequence>
+            <xs:element name="density" type="density" maxOccurs="unbounded" minOccurs="1">
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
 
+    <xs:complexType name="density">
+        <xs:sequence>
+            <xs:element type="xs:nonNegativeInteger" name="width">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+            <xs:element type="xs:nonNegativeInteger" name="height">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+            <xs:element type="xs:nonNegativeInteger" name="density">
+                <xs:annotation name="nonnull"/>
+                <xs:annotation name="final"/>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
 </xs:schema>
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index ad18602..5b2b87c 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -1,8 +1,24 @@
 // Signature format: 2.0
 package com.android.server.display.config {
 
+  public class Density {
+    ctor public Density();
+    method @NonNull public final java.math.BigInteger getDensity();
+    method @NonNull public final java.math.BigInteger getHeight();
+    method @NonNull public final java.math.BigInteger getWidth();
+    method public final void setDensity(@NonNull java.math.BigInteger);
+    method public final void setHeight(@NonNull java.math.BigInteger);
+    method public final void setWidth(@NonNull java.math.BigInteger);
+  }
+
+  public class DensityMap {
+    ctor public DensityMap();
+    method public java.util.List<com.android.server.display.config.Density> getDensity();
+  }
+
   public class DisplayConfiguration {
     ctor public DisplayConfiguration();
+    method @Nullable public final com.android.server.display.config.DensityMap getDensityMap();
     method public com.android.server.display.config.HighBrightnessMode getHighBrightnessMode();
     method public final com.android.server.display.config.SensorDetails getLightSensor();
     method public final com.android.server.display.config.SensorDetails getProxSensor();
@@ -13,6 +29,7 @@
     method public final java.math.BigDecimal getScreenBrightnessRampFastIncrease();
     method public final java.math.BigDecimal getScreenBrightnessRampSlowDecrease();
     method public final java.math.BigDecimal getScreenBrightnessRampSlowIncrease();
+    method public final void setDensityMap(@Nullable com.android.server.display.config.DensityMap);
     method public void setHighBrightnessMode(com.android.server.display.config.HighBrightnessMode);
     method public final void setLightSensor(com.android.server.display.config.SensorDetails);
     method public final void setProxSensor(com.android.server.display.config.SensorDetails);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index 37a84f3..df9ab50 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -16,7 +16,7 @@
 
 package com.android.server.devicepolicy;
 
-import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_DISABLED;
+import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY;
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
 import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
 
@@ -161,10 +161,10 @@
     int mPasswordComplexity = PASSWORD_COMPLEXITY_NONE;
 
     @DevicePolicyManager.NearbyStreamingPolicy
-    int mNearbyNotificationStreamingPolicy = NEARBY_STREAMING_DISABLED;
+    int mNearbyNotificationStreamingPolicy = NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY;
 
     @DevicePolicyManager.NearbyStreamingPolicy
-    int mNearbyAppStreamingPolicy = NEARBY_STREAMING_DISABLED;
+    int mNearbyAppStreamingPolicy = NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY;
 
     @Nullable
     FactoryResetProtectionPolicy mFactoryResetProtectionPolicy = null;
@@ -553,11 +553,11 @@
         if (mPasswordComplexity != PASSWORD_COMPLEXITY_NONE) {
             writeAttributeValueToXml(out, TAG_PASSWORD_COMPLEXITY, mPasswordComplexity);
         }
-        if (mNearbyNotificationStreamingPolicy != NEARBY_STREAMING_DISABLED) {
+        if (mNearbyNotificationStreamingPolicy != NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY) {
             writeAttributeValueToXml(out, TAG_NEARBY_NOTIFICATION_STREAMING_POLICY,
                     mNearbyNotificationStreamingPolicy);
         }
-        if (mNearbyAppStreamingPolicy != NEARBY_STREAMING_DISABLED) {
+        if (mNearbyAppStreamingPolicy != NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY) {
             writeAttributeValueToXml(out, TAG_NEARBY_APP_STREAMING_POLICY,
                     mNearbyAppStreamingPolicy);
         }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 727f265..be74ed8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8460,7 +8460,9 @@
     @Override
     public boolean hasDeviceOwner() {
         final CallerIdentity caller = getCallerIdentity();
-        Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
+        Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+                        || canManageUsers(caller)
+                        || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
         return mOwners.hasDeviceOwner();
     }
 
@@ -8640,7 +8642,8 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+                || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
 
         synchronized (getLockObject()) {
             if (!mOwners.hasDeviceOwner()) {
@@ -8986,7 +8989,8 @@
             return DevicePolicyManager.STATE_USER_UNMANAGED;
         }
         final CallerIdentity caller = getCallerIdentity();
-        Preconditions.checkCallAuthorization(canManageUsers(caller));
+        Preconditions.checkCallAuthorization(canManageUsers(caller)
+                || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
 
         return getUserProvisioningState(caller.getUserId());
     }
@@ -9240,7 +9244,8 @@
         if (!mHasFeature) {
             return null;
         }
-        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+                || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
         return getProfileOwnerNameUnchecked(userHandle);
     }
 
@@ -10394,14 +10399,23 @@
     }
 
     @Override
-    public List<String> getPermittedInputMethodsForCurrentUser() {
+    public @Nullable List<String> getPermittedInputMethodsAsUser(@UserIdInt int userId) {
         final CallerIdentity caller = getCallerIdentity();
+        Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId));
         Preconditions.checkCallAuthorization(canManageUsers(caller));
+        final long callingIdentity = Binder.clearCallingIdentity();
+        try {
+            return getPermittedInputMethodsUnchecked(userId);
+        } finally {
+            Binder.restoreCallingIdentity(callingIdentity);
+        }
+    }
 
+    private @Nullable List<String> getPermittedInputMethodsUnchecked(@UserIdInt int userId) {
         synchronized (getLockObject()) {
             List<String> result = null;
             // Only device or profile owners can have permitted lists set.
-            List<ActiveAdmin> admins = getActiveAdminsForAffectedUserLocked(caller.getUserId());
+            List<ActiveAdmin> admins = getActiveAdminsForAffectedUserLocked(userId);
             for (ActiveAdmin admin: admins) {
                 List<String> fromAdmin = admin.permittedInputMethods;
                 if (fromAdmin != null) {
@@ -10416,7 +10430,7 @@
             // If we have a permitted list add all system input methods.
             if (result != null) {
                 List<InputMethodInfo> imes = InputMethodManagerInternal
-                        .get().getInputMethodListAsUser(caller.getUserId());
+                        .get().getInputMethodListAsUser(userId);
                 if (imes != null) {
                     for (InputMethodInfo ime : imes) {
                         ServiceInfo serviceInfo = ime.getServiceInfo();
@@ -10582,7 +10596,12 @@
                         return null;
                     }
                 }
-                if (!mUserManager.canAddMoreUsers()) {
+
+                String userType = demo ? UserManager.USER_TYPE_FULL_DEMO
+                        : UserManager.USER_TYPE_FULL_SECONDARY;
+                int userInfoFlags = ephemeral ? UserInfo.FLAG_EPHEMERAL : 0;
+
+                if (!mUserManager.canAddMoreUsers(userType)) {
                     if (targetSdkVersion >= Build.VERSION_CODES.P) {
                         throw new ServiceSpecificException(
                                 UserManager.USER_OPERATION_ERROR_MAX_USERS, "user limit reached");
@@ -10591,9 +10610,6 @@
                     }
                 }
 
-                int userInfoFlags = ephemeral ? UserInfo.FLAG_EPHEMERAL : 0;
-                String userType = demo ? UserManager.USER_TYPE_FULL_DEMO
-                        : UserManager.USER_TYPE_FULL_SECONDARY;
                 String[] disallowedPackages = null;
                 if (!leaveAllSystemAppsEnabled) {
                     disallowedPackages = mOverlayPackagesProvider.getNonRequiredApps(admin,
@@ -16466,7 +16482,8 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+                || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
 
         long id = mInjector.binderClearCallingIdentity();
         try {
@@ -16492,7 +16509,8 @@
         if (!mHasFeature) {
             return false;
         }
-        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity()));
+        Preconditions.checkCallAuthorization(canManageUsers(getCallerIdentity())
+                || hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
 
         return mInjector.binderWithCleanCallingIdentity(() -> isUnattendedManagedKioskUnchecked());
     }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 752ad0b..a72cf3a 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -176,6 +176,7 @@
 import com.android.server.restrictions.RestrictionsManagerService;
 import com.android.server.role.RoleServicePlatformHelper;
 import com.android.server.rotationresolver.RotationResolverManagerService;
+import com.android.server.security.AttestationVerificationManagerService;
 import com.android.server.security.FileIntegrityService;
 import com.android.server.security.KeyAttestationApplicationIdProviderService;
 import com.android.server.security.KeyChainSystemService;
@@ -267,6 +268,8 @@
             "com.android.server.stats.StatsCompanion$Lifecycle";
     private static final String STATS_PULL_ATOM_SERVICE_CLASS =
             "com.android.server.stats.pull.StatsPullAtomService";
+    private static final String STATS_BOOTSTRAP_ATOM_SERVICE_LIFECYCLE_CLASS =
+            "com.android.server.stats.bootstrap.StatsBootstrapAtomService$Lifecycle";
     private static final String USB_SERVICE_CLASS =
             "com.android.server.usb.UsbService$Lifecycle";
     private static final String MIDI_SERVICE_CLASS =
@@ -371,6 +374,8 @@
             "com.android.server.blob.BlobStoreManagerService";
     private static final String APP_SEARCH_MANAGER_SERVICE_CLASS =
             "com.android.server.appsearch.AppSearchManagerService";
+    private static final String ISOLATED_COMPILATION_SERVICE_CLASS =
+            "com.android.server.compos.IsolatedCompilationService";
     private static final String ROLLBACK_MANAGER_SERVICE_CLASS =
             "com.android.server.rollback.RollbackManagerService";
     private static final String ALARM_MANAGER_SERVICE_CLASS =
@@ -394,6 +399,13 @@
     private static final String UWB_APEX_SERVICE_JAR_PATH =
             "/apex/com.android.uwb/javalib/service-uwb.jar";
     private static final String UWB_SERVICE_CLASS = "com.android.server.uwb.UwbService";
+    private static final String SAFETY_CENTER_SERVICE_CLASS =
+            "com.android.safetycenter.SafetyCenterService";
+
+    private static final String SUPPLEMENTALPROCESS_APEX_PATH =
+            "/apex/com.android.supplementalprocess/javalib/service-supplementalprocess.jar";
+    private static final String SUPPLEMENTALPROCESS_SERVICE_CLASS =
+            "com.android.server.supplementalprocess.SupplementalProcessManagerService$Lifecycle";
 
     private static final String TETHERING_CONNECTOR_CLASS = "android.net.ITetheringConnector";
 
@@ -631,7 +643,8 @@
         mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;
         mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
         mRuntimeStartUptime = SystemClock.uptimeMillis();
-        Process.setStartTimes(mRuntimeStartElapsedTime, mRuntimeStartUptime);
+        Process.setStartTimes(mRuntimeStartElapsedTime, mRuntimeStartUptime,
+                mRuntimeStartElapsedTime, mRuntimeStartUptime);
 
         // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
         // We don't use "mStartCount > 1" here because it'll be wrong on a FDE device.
@@ -2123,15 +2136,17 @@
                 t.traceEnd();
             }
 
-            t.traceBegin("StartWiredAccessoryManager");
-            try {
-                // Listen for wired headset changes
-                inputManager.setWiredAccessoryCallbacks(
-                        new WiredAccessoryManager(context, inputManager));
-            } catch (Throwable e) {
-                reportWtf("starting WiredAccessoryManager", e);
+            if (!isWatch) {
+                t.traceBegin("StartWiredAccessoryManager");
+                try {
+                    // Listen for wired headset changes
+                    inputManager.setWiredAccessoryCallbacks(
+                            new WiredAccessoryManager(context, inputManager));
+                } catch (Throwable e) {
+                    reportWtf("starting WiredAccessoryManager", e);
+                }
+                t.traceEnd();
             }
-            t.traceEnd();
 
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_MIDI)) {
                 // Start MIDI Manager service
@@ -2180,10 +2195,12 @@
                 Slog.e(TAG, "Failure starting HardwarePropertiesManagerService", e);
             }
             t.traceEnd();
-
-            t.traceBegin("StartTwilightService");
-            mSystemServiceManager.startService(TwilightService.class);
-            t.traceEnd();
+          
+            if (!isWatch) {
+                t.traceBegin("StartTwilightService");
+                mSystemServiceManager.startService(TwilightService.class);
+                t.traceEnd();
+            }
 
             t.traceBegin("StartColorDisplay");
             mSystemServiceManager.startService(ColorDisplayService.class);
@@ -2323,6 +2340,10 @@
                 t.traceEnd();
             }
 
+            t.traceBegin("StartAttestationVerificationService");
+            mSystemServiceManager.startService(AttestationVerificationManagerService.class);
+            t.traceEnd();
+
             if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_COMPANION_DEVICE_SETUP)) {
                 t.traceBegin("StartCompanionDeviceManager");
                 mSystemServiceManager.startService(COMPANION_DEVICE_MANAGER_SERVICE_CLASS);
@@ -2469,11 +2490,9 @@
             t.traceEnd();
         }
 
-        if (!isWatch) {
-            t.traceBegin("StartMediaProjectionManager");
-            mSystemServiceManager.startService(MediaProjectionManagerService.class);
-            t.traceEnd();
-        }
+        t.traceBegin("StartMediaProjectionManager");
+        mSystemServiceManager.startService(MediaProjectionManagerService.class);
+        t.traceEnd();
 
        if (isWatch) {
             // Must be started before services that depend it, e.g. WearConnectivityService
@@ -2533,11 +2552,22 @@
         mSystemServiceManager.startService(STATS_PULL_ATOM_SERVICE_CLASS);
         t.traceEnd();
 
+        // Log atoms to statsd from bootstrap processes.
+        t.traceBegin("StatsBootstrapAtomService");
+        mSystemServiceManager.startService(STATS_BOOTSTRAP_ATOM_SERVICE_LIFECYCLE_CLASS);
+        t.traceEnd();
+
         // Incidentd and dumpstated helper
         t.traceBegin("StartIncidentCompanionService");
         mSystemServiceManager.startService(IncidentCompanionService.class);
         t.traceEnd();
 
+        // Supplemental Process
+        t.traceBegin("StartSupplementalProcessManagerService");
+        mSystemServiceManager.startServiceFromJar(SUPPLEMENTALPROCESS_SERVICE_CLASS,
+                SUPPLEMENTALPROCESS_APEX_PATH);
+        t.traceEnd();
+
         if (safeMode) {
             mActivityManagerService.enterSafeMode();
         }
@@ -2693,10 +2723,20 @@
         mSystemServiceManager.startBootPhase(t, SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
         t.traceEnd();
 
+        t.traceBegin("StartSafetyCenterService");
+        mSystemServiceManager.startService(SAFETY_CENTER_SERVICE_CLASS);
+        t.traceEnd();
+
         t.traceBegin("AppSearchManagerService");
         mSystemServiceManager.startService(APP_SEARCH_MANAGER_SERVICE_CLASS);
         t.traceEnd();
 
+        if (SystemProperties.getBoolean("ro.config.isolated_compilation_enabled", false)) {
+            t.traceBegin("IsolatedCompilationService");
+            mSystemServiceManager.startService(ISOLATED_COMPILATION_SERVICE_CLASS);
+            t.traceEnd();
+        }
+
         t.traceBegin("StartMediaCommunicationService");
         mSystemServiceManager.startService(MEDIA_COMMUNICATION_SERVICE_CLASS);
         t.traceEnd();
diff --git a/services/net/OWNERS b/services/net/OWNERS
index d3836d4..62c5737 100644
--- a/services/net/OWNERS
+++ b/services/net/OWNERS
@@ -1,8 +1,2 @@
 set noparent
-
-codewiz@google.com
-jchalard@google.com
-junyulai@google.com
-lorenzo@google.com
-reminv@google.com
-satk@google.com
+file:platform/packages/modules/Connectivity:master:/OWNERS_core_networking
diff --git a/services/people/java/com/android/server/people/data/CallLogQueryHelper.java b/services/people/java/com/android/server/people/data/CallLogQueryHelper.java
index 45e0aac..ff901af 100644
--- a/services/people/java/com/android/server/people/data/CallLogQueryHelper.java
+++ b/services/people/java/com/android/server/people/data/CallLogQueryHelper.java
@@ -93,6 +93,9 @@
                     hasResults = true;
                 }
             }
+        } catch (SecurityException ex) {
+            Slog.e(TAG, "Query call log failed: " + ex);
+            return false;
         }
         return hasResults;
     }
diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
index 8369319..62a16f7 100644
--- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
+++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java
@@ -91,10 +91,12 @@
             if (mIProfcollect == null) {
                 return;
             }
-            if (serviceHasSupportedTraceProvider()) {
-                registerObservers();
-            }
-            ProfcollectBGJobService.schedule(getContext());
+            BackgroundThread.get().getThreadHandler().post(() -> {
+                if (serviceHasSupportedTraceProvider()) {
+                    registerObservers();
+                    ProfcollectBGJobService.schedule(getContext());
+                }
+            });
         }
     }
 
@@ -234,14 +236,16 @@
                 "applaunch_trace_freq", 2);
         int randomNum = ThreadLocalRandom.current().nextInt(100);
         if (randomNum < traceFrequency) {
-            try {
-                if (DEBUG) {
-                    Log.d(LOG_TAG, "Tracing on app launch event: " + packageName);
-                }
-                mIProfcollect.trace_once("applaunch");
-            } catch (RemoteException e) {
-                Log.e(LOG_TAG, e.getMessage());
+            if (DEBUG) {
+                Log.d(LOG_TAG, "Tracing on app launch event: " + packageName);
             }
+            BackgroundThread.get().getThreadHandler().post(() -> {
+                try {
+                    mIProfcollect.trace_once("applaunch");
+                } catch (RemoteException e) {
+                    Log.e(LOG_TAG, e.getMessage());
+                }
+            });
         }
     }
 
diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
index 349eb22..dc93e53 100644
--- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
+++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt
@@ -223,6 +223,7 @@
         AndroidPackage::isVendor,
         AndroidPackage::isVisibleToInstantApps,
         AndroidPackage::isVmSafeMode,
+        AndroidPackage::isResetEnabledSettingsOnAppDataCleared,
         AndroidPackage::getMaxAspectRatio,
         AndroidPackage::getMinAspectRatio,
         AndroidPackage::hasPreserveLegacyExternalStorage,
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 284a754..1ef9d13 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -67,7 +67,6 @@
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
-import static org.mockito.Mockito.anyLong;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.doNothing;
@@ -2180,7 +2179,7 @@
         record.addConnection(binder, cr);
         client.mServices.addConnection(cr);
         binding.connections.add(cr);
-        doNothing().when(cr).trackProcState(anyInt(), anyInt(), anyLong());
+        doNothing().when(cr).trackProcState(anyInt(), anyInt());
         return record;
     }
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java
index 41e1237..17d7c51 100644
--- a/services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/communal/CommunalManagerServiceTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.communal;
 
+import static android.app.communal.CommunalManager.ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT;
 import static android.content.Intent.ACTION_PACKAGE_REMOVED;
 import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
 
@@ -23,7 +24,6 @@
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
-import static com.android.server.communal.CommunalManagerService.ALLOW_COMMUNAL_MODE_WITH_USER_CONSENT;
 import static com.android.server.wm.ActivityInterceptorCallback.COMMUNAL_MODE_ORDERED_ID;
 
 import static com.google.common.truth.Truth.assertThat;
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DensityMapTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DensityMapTest.java
new file mode 100644
index 0000000..3f69f1b
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DensityMapTest.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2021 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.display;
+
+import static com.android.server.display.DensityMap.Entry;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DensityMapTest {
+
+    @Test
+    public void testConstructor_withBadConfig_throwsException() {
+        assertThrows(IllegalStateException.class, () ->
+                DensityMap.createByOwning(new Entry[]{
+                        new Entry(1080, 1920, 320),
+                        new Entry(1080, 1920, 320)})
+        );
+
+        assertThrows(IllegalStateException.class, () ->
+                DensityMap.createByOwning(new Entry[]{
+                        new Entry(1080, 1920, 320),
+                        new Entry(1920, 1080, 120)})
+        );
+
+        assertThrows(IllegalStateException.class, () ->
+                DensityMap.createByOwning(new Entry[]{
+                        new Entry(1080, 1920, 320),
+                        new Entry(2160, 3840, 120)})
+        );
+
+        assertThrows(IllegalStateException.class, () ->
+                DensityMap.createByOwning(new Entry[]{
+                        new Entry(1080, 1920, 320),
+                        new Entry(3840, 2160, 120)})
+        );
+
+        // Two entries with the same diagonal
+        assertThrows(IllegalStateException.class, () ->
+                DensityMap.createByOwning(new Entry[]{
+                        new Entry(500, 500, 123),
+                        new Entry(100, 700, 456)})
+        );
+    }
+
+    @Test
+    public void testGetDensityForResolution_withResolutionMatch_returnsDensityFromConfig() {
+        DensityMap densityMap = DensityMap.createByOwning(new Entry[]{
+                new Entry(720, 1280, 213),
+                new Entry(1080, 1920, 320),
+                new Entry(2160, 3840, 640)});
+
+        assertEquals(213, densityMap.getDensityForResolution(720, 1280));
+        assertEquals(213, densityMap.getDensityForResolution(1280, 720));
+
+        assertEquals(320, densityMap.getDensityForResolution(1080, 1920));
+        assertEquals(320, densityMap.getDensityForResolution(1920, 1080));
+
+        assertEquals(640, densityMap.getDensityForResolution(2160, 3840));
+        assertEquals(640, densityMap.getDensityForResolution(3840, 2160));
+    }
+
+    @Test
+    public void testGetDensityForResolution_withDiagonalMatch_returnsDensityFromConfig() {
+        DensityMap densityMap = DensityMap.createByOwning(
+                        new Entry[]{ new Entry(500, 500, 123)});
+
+        // 500x500 has the same diagonal as 100x700
+        assertEquals(123, densityMap.getDensityForResolution(100, 700));
+    }
+
+    @Test
+    public void testGetDensityForResolution_withOneEntry_withNoMatch_returnsExtrapolatedDensity() {
+        DensityMap densityMap = DensityMap.createByOwning(
+                new Entry[]{ new Entry(1080, 1920, 320)});
+
+        assertEquals(320, densityMap.getDensityForResolution(1081, 1920));
+        assertEquals(320, densityMap.getDensityForResolution(1080, 1921));
+
+        assertEquals(640, densityMap.getDensityForResolution(2160, 3840));
+        assertEquals(640, densityMap.getDensityForResolution(3840, 2160));
+
+        assertEquals(213, densityMap.getDensityForResolution(720, 1280));
+        assertEquals(213, densityMap.getDensityForResolution(1280, 720));
+    }
+
+    @Test
+    public void testGetDensityForResolution_withTwoEntries_withNoMatch_returnExtrapolatedDensity() {
+        DensityMap densityMap = DensityMap.createByOwning(new Entry[]{
+                new Entry(1080, 1920, 320),
+                new Entry(2160, 3840, 320)});
+
+        // Resolution is smaller than all entries
+        assertEquals(213, densityMap.getDensityForResolution(720, 1280));
+        assertEquals(213, densityMap.getDensityForResolution(1280, 720));
+
+        // Resolution is bigger than all entries
+        assertEquals(320 * 2, densityMap.getDensityForResolution(2160 * 2, 3840 * 2));
+        assertEquals(320 * 2, densityMap.getDensityForResolution(3840 * 2, 2160 * 2));
+    }
+
+    @Test
+    public void testGetDensityForResolution_withNoMatch_returnsInterpolatedDensity() {
+        {
+            DensityMap densityMap = DensityMap.createByOwning(new Entry[]{
+                    new Entry(1080, 1920, 320),
+                    new Entry(2160, 3840, 320)});
+
+            assertEquals(320, densityMap.getDensityForResolution(2000, 2000));
+        }
+
+        {
+            DensityMap densityMap = DensityMap.createByOwning(new Entry[]{
+                    new Entry(720, 1280, 213),
+                    new Entry(2160, 3840, 640)});
+
+            assertEquals(320, densityMap.getDensityForResolution(1080, 1920));
+            assertEquals(320, densityMap.getDensityForResolution(1920, 1080));
+        }
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
index e5b2d14..95912b2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/PrefetchControllerTest.java
@@ -43,12 +43,16 @@
 import android.app.job.JobInfo;
 import android.app.usage.UsageStatsManagerInternal;
 import android.app.usage.UsageStatsManagerInternal.EstimatedLaunchTimeChangedListener;
+import android.appwidget.AppWidgetManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ServiceInfo;
 import android.os.Looper;
+import android.os.Process;
 import android.os.SystemClock;
 import android.provider.DeviceConfig;
+import android.util.ArraySet;
+import android.util.SparseArray;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -85,6 +89,7 @@
     private PcConstants mPcConstants;
     private DeviceConfig.Properties.Builder mDeviceConfigPropertiesBuilder;
     private EstimatedLaunchTimeChangedListener mEstimatedLaunchTimeChangedListener;
+    private SparseArray<ArraySet<String>> mPackagesForUid = new SparseArray<>();
 
     private MockitoSession mMockingSession;
     @Mock
@@ -125,6 +130,10 @@
                         -> mDeviceConfigPropertiesBuilder.build())
                 .when(() -> DeviceConfig.getProperties(
                         eq(DeviceConfig.NAMESPACE_JOB_SCHEDULER), ArgumentMatchers.<String>any()));
+        // Used in PrefetchController.maybeUpdateConstraintForUid
+        when(mJobSchedulerService.getPackagesForUidLocked(anyInt()))
+                .thenAnswer(invocationOnMock
+                        -> mPackagesForUid.get(invocationOnMock.getArgument(0)));
 
         // Freeze the clocks at 24 hours after this moment in time. Several tests create sessions
         // in the past, and PrefetchController sometimes floors values at 0, so if the test time
@@ -146,6 +155,8 @@
         mPrefetchController = new PrefetchController(mJobSchedulerService);
         mPcConstants = mPrefetchController.getPcConstants();
 
+        setUidBias(Process.myUid(), JobInfo.BIAS_DEFAULT);
+
         verify(mUsageStatsManagerInternal)
                 .registerLaunchTimeChangedListener(eltListenerCaptor.capture());
         mEstimatedLaunchTimeChangedListener = eltListenerCaptor.getValue();
@@ -158,12 +169,15 @@
         }
     }
 
-    private JobStatus createJobStatus(String testTag, int jobId) {
-        JobInfo jobInfo = new JobInfo.Builder(jobId,
+    private JobInfo createJobInfo(int jobId) {
+        return new JobInfo.Builder(jobId,
                 new ComponentName(mContext, "TestPrefetchJobService"))
                 .setPrefetch(true)
                 .build();
-        return createJobStatus(testTag, SOURCE_PACKAGE, CALLING_UID, jobInfo);
+    }
+
+    private JobStatus createJobStatus(String testTag, int jobId) {
+        return createJobStatus(testTag, SOURCE_PACKAGE, CALLING_UID, createJobInfo(jobId));
     }
 
     private static JobStatus createJobStatus(String testTag, String packageName, int callingUid,
@@ -185,6 +199,12 @@
         return Clock.offset(clock, Duration.ofMillis(incrementMs));
     }
 
+    private void setUidBias(int uid, int bias) {
+        synchronized (mPrefetchController.mLock) {
+            mPrefetchController.onUidBiasChangedLocked(uid, bias);
+        }
+    }
+
     private void setDeviceConfigLong(String key, long val) {
         mDeviceConfigPropertiesBuilder.setLong(key, val);
         synchronized (mPrefetchController.mLock) {
@@ -196,6 +216,12 @@
 
     private void trackJobs(JobStatus... jobs) {
         for (JobStatus job : jobs) {
+            ArraySet<String> pkgs = mPackagesForUid.get(job.getSourceUid());
+            if (pkgs == null) {
+                pkgs = new ArraySet<>();
+                mPackagesForUid.put(job.getSourceUid(), pkgs);
+            }
+            pkgs.add(job.getSourcePackageName());
             synchronized (mPrefetchController.mLock) {
                 mPrefetchController.maybeStartTrackingJobLocked(job, null);
             }
@@ -269,10 +295,72 @@
         trackJobs(job);
         verify(mUsageStatsManagerInternal, timeout(DEFAULT_WAIT_MS))
                 .getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID);
+        verify(mJobSchedulerService, timeout(DEFAULT_WAIT_MS)).onControllerStateChanged(any());
         assertTrue(job.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
     }
 
     @Test
+    public void testConstraintSatisfiedWhenTop() {
+        final JobStatus jobPending = createJobStatus("testConstraintSatisfiedWhenTop", 1);
+        final JobStatus jobRunning = createJobStatus("testConstraintSatisfiedWhenTop", 2);
+        final int uid = jobPending.getSourceUid();
+
+        when(mJobSchedulerService.isCurrentlyRunningLocked(jobPending)).thenReturn(false);
+        when(mJobSchedulerService.isCurrentlyRunningLocked(jobRunning)).thenReturn(true);
+
+        InOrder inOrder = inOrder(mJobSchedulerService);
+
+        when(mUsageStatsManagerInternal
+                .getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
+                .thenReturn(sSystemClock.millis() + 10 * MINUTE_IN_MILLIS);
+        trackJobs(jobPending, jobRunning);
+        verify(mUsageStatsManagerInternal, timeout(DEFAULT_WAIT_MS))
+                .getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID);
+        inOrder.verify(mJobSchedulerService, timeout(DEFAULT_WAIT_MS))
+                .onControllerStateChanged(any());
+        assertTrue(jobPending.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
+        assertTrue(jobRunning.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
+        setUidBias(uid, JobInfo.BIAS_TOP_APP);
+        // Processing happens on the handler, so wait until we're sure the change has been processed
+        inOrder.verify(mJobSchedulerService, timeout(DEFAULT_WAIT_MS))
+                .onControllerStateChanged(any());
+        // Already running job should continue but pending job must wait.
+        assertFalse(jobPending.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
+        assertTrue(jobRunning.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
+        setUidBias(uid, JobInfo.BIAS_DEFAULT);
+        inOrder.verify(mJobSchedulerService, timeout(DEFAULT_WAIT_MS))
+                .onControllerStateChanged(any());
+        assertTrue(jobPending.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
+        assertTrue(jobRunning.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
+    }
+
+    @Test
+    public void testConstraintSatisfiedWhenWidget() {
+        final JobStatus jobNonWidget = createJobStatus("testConstraintSatisfiedWhenWidget", 1);
+        final JobStatus jobWidget = createJobStatus("testConstraintSatisfiedWhenWidget", 2);
+
+        when(mUsageStatsManagerInternal
+                .getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID))
+                .thenReturn(sSystemClock.millis() + 100 * HOUR_IN_MILLIS);
+
+        final AppWidgetManager appWidgetManager = mock(AppWidgetManager.class);
+        when(mContext.getSystemService(AppWidgetManager.class)).thenReturn(appWidgetManager);
+        mPrefetchController.onSystemServicesReady();
+
+        when(appWidgetManager.isBoundWidgetPackage(SOURCE_PACKAGE, SOURCE_USER_ID))
+                .thenReturn(false);
+        trackJobs(jobNonWidget);
+        verify(mUsageStatsManagerInternal, timeout(DEFAULT_WAIT_MS))
+                .getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID);
+        assertFalse(jobNonWidget.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
+
+        when(appWidgetManager.isBoundWidgetPackage(SOURCE_PACKAGE, SOURCE_USER_ID))
+                .thenReturn(true);
+        trackJobs(jobWidget);
+        assertTrue(jobWidget.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
+    }
+
+    @Test
     public void testEstimatedLaunchTimeChangedToLate() {
         setDeviceConfigLong(PcConstants.KEY_LAUNCH_TIME_THRESHOLD_MS, 7 * HOUR_IN_MILLIS);
         when(mUsageStatsManagerInternal
@@ -285,6 +373,7 @@
         trackJobs(jobStatus);
         inOrder.verify(mUsageStatsManagerInternal, timeout(DEFAULT_WAIT_MS))
                 .getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID);
+        verify(mJobSchedulerService, timeout(DEFAULT_WAIT_MS)).onControllerStateChanged(any());
         assertTrue(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
 
         mEstimatedLaunchTimeChangedListener.onEstimatedLaunchTimeChanged(SOURCE_USER_ID,
@@ -315,6 +404,7 @@
 
         inOrder.verify(mUsageStatsManagerInternal, timeout(DEFAULT_WAIT_MS).times(0))
                 .getEstimatedPackageLaunchTime(SOURCE_PACKAGE, SOURCE_USER_ID);
+        verify(mJobSchedulerService, timeout(DEFAULT_WAIT_MS)).onControllerStateChanged(any());
         assertTrue(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_PREFETCH));
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java b/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java
index e2e7f5d..94dcdf9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/injector/LocationAttributionHelperTest.java
@@ -58,72 +58,86 @@
     @Test
     public void testLocationMonitoring() {
         CallerIdentity caller1 = CallerIdentity.forTest(1, 1, "test1", null);
-        Object key1 = new Object();
-        Object key2 = new Object();
         CallerIdentity caller2 = CallerIdentity.forTest(2, 2, "test2", null);
-        Object key3 = new Object();
-        Object key4 = new Object();
 
-        mHelper.reportLocationStart(caller1, "gps", key1);
-        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller1);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller1);
+        mHelper.reportLocationStart(caller1);
+        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION,
+                CallerIdentity.forAggregation(caller1));
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+                CallerIdentity.forAggregation(caller1));
 
-        mHelper.reportLocationStart(caller1, "gps", key2);
-        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller1);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller1);
+        mHelper.reportLocationStart(caller1);
+        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION,
+                CallerIdentity.forAggregation(caller1));
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+                CallerIdentity.forAggregation(caller1));
 
-        mHelper.reportLocationStart(caller2, "gps", key3);
-        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller2);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller2);
+        mHelper.reportLocationStart(caller2);
+        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION,
+                CallerIdentity.forAggregation(caller2));
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+                CallerIdentity.forAggregation(caller2));
 
-        mHelper.reportLocationStart(caller2, "gps", key4);
-        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION, caller2);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller2);
+        mHelper.reportLocationStart(caller2);
+        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_LOCATION,
+                CallerIdentity.forAggregation(caller2));
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+                CallerIdentity.forAggregation(caller2));
 
-        mHelper.reportLocationStop(caller1, "gps", key2);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller1);
-        mHelper.reportLocationStop(caller1, "gps", key1);
-        verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, caller1);
+        mHelper.reportLocationStop(caller1);
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+                CallerIdentity.forAggregation(caller1));
+        mHelper.reportLocationStop(caller1);
+        verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, CallerIdentity.forAggregation(caller1));
 
-        mHelper.reportLocationStop(caller2, "gps", key3);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION, caller2);
-        mHelper.reportLocationStop(caller2, "gps", key4);
-        verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, caller2);
+        mHelper.reportLocationStop(caller2);
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_LOCATION,
+                CallerIdentity.forAggregation(caller2));
+        mHelper.reportLocationStop(caller2);
+        verify(mAppOpsHelper).finishOp(OP_MONITOR_LOCATION, CallerIdentity.forAggregation(caller2));
     }
 
     @Test
     public void testHighPowerLocationMonitoring() {
         CallerIdentity caller1 = CallerIdentity.forTest(1, 1, "test1", null);
-        Object key1 = new Object();
-        Object key2 = new Object();
         CallerIdentity caller2 = CallerIdentity.forTest(2, 2, "test2", null);
-        Object key3 = new Object();
-        Object key4 = new Object();
 
-        mHelper.reportHighPowerLocationStart(caller1, "gps", key1);
-        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
+        mHelper.reportHighPowerLocationStart(caller1);
+        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller1));
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller1));
 
-        mHelper.reportHighPowerLocationStart(caller1, "gps", key2);
-        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
+        mHelper.reportHighPowerLocationStart(caller1);
+        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller1));
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller1));
 
-        mHelper.reportHighPowerLocationStart(caller2, "gps", key3);
-        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
+        mHelper.reportHighPowerLocationStart(caller2);
+        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller2));
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller2));
 
-        mHelper.reportHighPowerLocationStart(caller2, "gps", key4);
-        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
+        mHelper.reportHighPowerLocationStart(caller2);
+        verify(mAppOpsHelper).startOpNoThrow(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller2));
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller2));
 
-        mHelper.reportHighPowerLocationStop(caller1, "gps", key2);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
-        mHelper.reportHighPowerLocationStop(caller1, "gps", key1);
-        verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller1);
+        mHelper.reportHighPowerLocationStop(caller1);
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller1));
+        mHelper.reportHighPowerLocationStop(caller1);
+        verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller1));
 
-        mHelper.reportHighPowerLocationStop(caller2, "gps", key3);
-        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
-        mHelper.reportHighPowerLocationStop(caller2, "gps", key4);
-        verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION, caller2);
+        mHelper.reportHighPowerLocationStop(caller2);
+        verify(mAppOpsHelper, never()).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller2));
+        mHelper.reportHighPowerLocationStop(caller2);
+        verify(mAppOpsHelper).finishOp(OP_MONITOR_HIGH_POWER_LOCATION,
+                CallerIdentity.forAggregation(caller2));
     }
 }
diff --git a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
index d0b2eda..890a549 100644
--- a/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/location/provider/LocationProviderManagerTest.java
@@ -845,6 +845,48 @@
     }
 
     @Test
+    public void testLocationMonitoring_multipleIdentities() {
+        CallerIdentity identity1 = CallerIdentity.forTest(CURRENT_USER, 1,
+                "mypackage", "attribution", "listener1");
+        CallerIdentity identity2 = CallerIdentity.forTest(CURRENT_USER, 1,
+                "mypackage", "attribution", "listener2");
+
+        assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
+                IDENTITY.getPackageName())).isFalse();
+        assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
+                IDENTITY.getPackageName())).isFalse();
+
+        ILocationListener listener1 = createMockLocationListener();
+        LocationRequest request1 = new LocationRequest.Builder(0).setWorkSource(
+                WORK_SOURCE).build();
+        mManager.registerLocationRequest(request1, identity1, PERMISSION_FINE, listener1);
+
+        ILocationListener listener2 = createMockLocationListener();
+        LocationRequest request2 = new LocationRequest.Builder(0).setWorkSource(
+                WORK_SOURCE).build();
+        mManager.registerLocationRequest(request2, identity2, PERMISSION_FINE, listener2);
+
+        assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
+                "mypackage")).isTrue();
+        assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
+                "mypackage")).isTrue();
+
+        mManager.unregisterLocationRequest(listener2);
+
+        assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
+                "mypackage")).isTrue();
+        assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
+                "mypackage")).isTrue();
+
+        mManager.unregisterLocationRequest(listener1);
+
+        assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_LOCATION,
+                "mypackage")).isFalse();
+        assertThat(mInjector.getAppOpsHelper().isAppOpStarted(OP_MONITOR_HIGH_POWER_LOCATION,
+                "mypackage")).isFalse();
+    }
+
+    @Test
     public void testProviderRequest() {
         assertThat(mProvider.getRequest().isActive()).isFalse();
 
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java
new file mode 100644
index 0000000..8223b8c
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/BackgroundDexOptServiceUnitTest.java
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2021 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.assertThrows;
+
+import android.app.job.JobInfo;
+import android.app.job.JobParameters;
+import android.app.job.JobScheduler;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.HandlerThread;
+import android.os.PowerManager;
+import android.util.ArraySet;
+
+import com.android.server.LocalServices;
+import com.android.server.PinnerService;
+import com.android.server.pm.dex.DexManager;
+import com.android.server.pm.dex.DexoptOptions;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.stream.Collectors;
+
+@RunWith(MockitoJUnitRunner.class)
+public final class BackgroundDexOptServiceUnitTest {
+    private static final String TAG = BackgroundDexOptServiceUnitTest.class.getSimpleName();
+
+    private static final long USABLE_SPACE_NORMAL = 1_000_000_000;
+    private static final long STORAGE_LOW_BYTES = 1_000_000;
+
+    private static final long TEST_WAIT_TIMEOUT_MS = 10_000;
+
+    private static final ArraySet<String> DEFAULT_PACKAGE_LIST = new ArraySet<>(
+            Arrays.asList("aaa", "bbb"));
+    private static final ArraySet<String> EMPTY_PACKAGE_LIST = new ArraySet<>();
+
+    @Mock
+    private Context mContext;
+    @Mock
+    private PackageManagerService mPackageManager;
+    @Mock
+    private DexOptHelper mDexOptHelper;
+    @Mock
+    private DexManager mDexManager;
+    @Mock
+    private PinnerService mPinnerService;
+    @Mock
+    private JobScheduler mJobScheduler;
+    @Mock
+    private BackgroundDexOptService.Injector mInjector;
+    @Mock
+    private BackgroundDexOptJobService mJobServiceForPostBoot;
+    @Mock
+    private BackgroundDexOptJobService mJobServiceForIdle;
+
+    private final JobParameters mJobParametersForPostBoot = new JobParameters(null,
+            BackgroundDexOptService.JOB_POST_BOOT_UPDATE, null, null, null,
+            0, false, false, null, null, null);
+    private final JobParameters mJobParametersForIdle = new JobParameters(null,
+            BackgroundDexOptService.JOB_IDLE_OPTIMIZE, null, null, null,
+            0, false, false, null, null, null);
+
+    private BackgroundDexOptService mService;
+
+    private StartAndWaitThread mDexOptThread;
+    private StartAndWaitThread mCancelThread;
+
+    @Before
+    public void setUp() throws Exception {
+        when(mInjector.getContext()).thenReturn(mContext);
+        when(mInjector.getDexOptHelper()).thenReturn(mDexOptHelper);
+        when(mInjector.getDexManager()).thenReturn(mDexManager);
+        when(mInjector.getPinnerService()).thenReturn(mPinnerService);
+        when(mInjector.getJobScheduler()).thenReturn(mJobScheduler);
+        when(mInjector.getPackageManagerService()).thenReturn(mPackageManager);
+
+        // These mocking can be overwritten in some tests but still keep it here as alternative
+        // takes too many repetitive codes.
+        when(mInjector.getDataDirUsableSpace()).thenReturn(USABLE_SPACE_NORMAL);
+        when(mInjector.getDataDirStorageLowBytes()).thenReturn(STORAGE_LOW_BYTES);
+        when(mInjector.getDexOptThermalCutoff()).thenReturn(PowerManager.THERMAL_STATUS_CRITICAL);
+        when(mInjector.getCurrentThermalStatus()).thenReturn(PowerManager.THERMAL_STATUS_NONE);
+        when(mDexOptHelper.getOptimizablePackages()).thenReturn(DEFAULT_PACKAGE_LIST);
+        when(mDexOptHelper.performDexOptWithStatus(any())).thenReturn(
+                PackageDexOptimizer.DEX_OPT_PERFORMED);
+
+        mService = new BackgroundDexOptService(mInjector);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        LocalServices.removeServiceForTest(BackgroundDexOptService.class);
+    }
+
+    @Test
+    public void testGetService() {
+        assertThat(BackgroundDexOptService.getService()).isEqualTo(mService);
+    }
+
+    @Test
+    public void testBootCompleted() {
+        initUntilBootCompleted();
+    }
+
+    @Test
+    public void testNoExecutionForIdleJobBeforePostBootUpdate() {
+        initUntilBootCompleted();
+
+        assertThat(mService.onStartJob(mJobServiceForIdle, mJobParametersForIdle)).isFalse();
+    }
+
+    @Test
+    public void testNoExecutionForLowStorage() {
+        initUntilBootCompleted();
+        when(mPackageManager.isStorageLow()).thenReturn(true);
+
+        assertThat(mService.onStartJob(mJobServiceForPostBoot,
+                mJobParametersForPostBoot)).isFalse();
+        verify(mDexOptHelper, never()).performDexOpt(any());
+    }
+
+    @Test
+    public void testNoExecutionForNoOptimizablePackages() {
+        initUntilBootCompleted();
+        when(mDexOptHelper.getOptimizablePackages()).thenReturn(EMPTY_PACKAGE_LIST);
+
+        assertThat(mService.onStartJob(mJobServiceForPostBoot,
+                mJobParametersForPostBoot)).isFalse();
+        verify(mDexOptHelper, never()).performDexOpt(any());
+    }
+
+    @Test
+    public void testPostBootUpdateFullRun() {
+        initUntilBootCompleted();
+
+        runFullJob(mJobServiceForPostBoot, mJobParametersForPostBoot, false, 1);
+    }
+
+    @Test
+    public void testIdleJobFullRun() {
+        initUntilBootCompleted();
+
+        runFullJob(mJobServiceForPostBoot, mJobParametersForPostBoot, false, 1);
+        runFullJob(mJobServiceForIdle, mJobParametersForIdle, true, 2);
+    }
+
+    @Test
+    public void testSystemReadyWhenDisabled() {
+        when(mInjector.isBackgroundDexOptDisabled()).thenReturn(true);
+
+        mService.systemReady();
+
+        verify(mContext, never()).registerReceiver(any(), any());
+    }
+
+    @Test
+    public void testStopByCancelFlag() {
+        when(mInjector.createAndStartThread(any(), any())).thenReturn(Thread.currentThread());
+        initUntilBootCompleted();
+
+        assertThat(mService.onStartJob(mJobServiceForPostBoot, mJobParametersForPostBoot)).isTrue();
+
+        ArgumentCaptor<Runnable> argDexOptThreadRunnable = ArgumentCaptor.forClass(Runnable.class);
+        verify(mInjector, atLeastOnce()).createAndStartThread(any(),
+                argDexOptThreadRunnable.capture());
+
+        // Stopping requires a separate thread
+        HandlerThread cancelThread = new HandlerThread("Stopping");
+        cancelThread.start();
+        when(mInjector.createAndStartThread(any(), any())).thenReturn(cancelThread);
+
+        // Cancel
+        assertThat(mService.onStopJob(mJobServiceForPostBoot, mJobParametersForPostBoot)).isTrue();
+
+        // Capture Runnable for cancel
+        ArgumentCaptor<Runnable> argCancelThreadRunnable = ArgumentCaptor.forClass(Runnable.class);
+        verify(mInjector, atLeastOnce()).createAndStartThread(any(),
+                argCancelThreadRunnable.capture());
+
+        // Execute cancelling part
+        cancelThread.getThreadHandler().post(argCancelThreadRunnable.getValue());
+
+        verify(mDexOptHelper, timeout(TEST_WAIT_TIMEOUT_MS)).controlDexOptBlocking(true);
+
+        // Dexopt thread run and cancelled
+        argDexOptThreadRunnable.getValue().run();
+
+        // Wait until cancellation Runnable is completed.
+        assertThat(cancelThread.getThreadHandler().runWithScissors(
+                argCancelThreadRunnable.getValue(), TEST_WAIT_TIMEOUT_MS)).isTrue();
+
+        // Now cancel completed
+        verify(mJobServiceForPostBoot).jobFinished(mJobParametersForPostBoot, true);
+        verifyLastControlDexOptBlockingCall(false);
+    }
+
+    @Test
+    public void testPostUpdateCancelFirst() throws Exception {
+        initUntilBootCompleted();
+        when(mInjector.createAndStartThread(any(), any())).thenAnswer(
+                i -> createAndStartExecutionThread(i.getArgument(0), i.getArgument(1)));
+
+        // Start
+        assertThat(mService.onStartJob(mJobServiceForPostBoot, mJobParametersForPostBoot)).isTrue();
+        // Cancel
+        assertThat(mService.onStopJob(mJobServiceForPostBoot, mJobParametersForPostBoot)).isTrue();
+
+        mCancelThread.runActualRunnable();
+
+        // Wait until cancel has set the flag.
+        verify(mDexOptHelper, timeout(TEST_WAIT_TIMEOUT_MS)).controlDexOptBlocking(
+                true);
+
+        mDexOptThread.runActualRunnable();
+
+        // All threads should finish.
+        mDexOptThread.join(TEST_WAIT_TIMEOUT_MS);
+        mCancelThread.join(TEST_WAIT_TIMEOUT_MS);
+
+        // Retry later if post boot job was cancelled
+        verify(mJobServiceForPostBoot).jobFinished(mJobParametersForPostBoot, true);
+        verifyLastControlDexOptBlockingCall(false);
+    }
+
+    @Test
+    public void testPostUpdateCancelLater() throws Exception {
+        initUntilBootCompleted();
+        when(mInjector.createAndStartThread(any(), any())).thenAnswer(
+                i -> createAndStartExecutionThread(i.getArgument(0), i.getArgument(1)));
+
+        // Start
+        assertThat(mService.onStartJob(mJobServiceForPostBoot, mJobParametersForPostBoot)).isTrue();
+        // Cancel
+        assertThat(mService.onStopJob(mJobServiceForPostBoot, mJobParametersForPostBoot)).isTrue();
+
+        // Dexopt thread runs and finishes
+        mDexOptThread.runActualRunnable();
+        mDexOptThread.join(TEST_WAIT_TIMEOUT_MS);
+
+        mCancelThread.runActualRunnable();
+        mCancelThread.join(TEST_WAIT_TIMEOUT_MS);
+
+        // Already completed before cancel, so no rescheduling.
+        verify(mJobServiceForPostBoot).jobFinished(mJobParametersForPostBoot, false);
+        verify(mDexOptHelper, never()).controlDexOptBlocking(true);
+    }
+
+    @Test
+    public void testPeriodicJobCancelFirst() throws Exception {
+        initUntilBootCompleted();
+        when(mInjector.createAndStartThread(any(), any())).thenAnswer(
+                i -> createAndStartExecutionThread(i.getArgument(0), i.getArgument(1)));
+
+        // Start and finish post boot job
+        assertThat(mService.onStartJob(mJobServiceForPostBoot, mJobParametersForPostBoot)).isTrue();
+        mDexOptThread.runActualRunnable();
+        mDexOptThread.join(TEST_WAIT_TIMEOUT_MS);
+
+        // Start
+        assertThat(mService.onStartJob(mJobServiceForIdle, mJobParametersForIdle)).isTrue();
+        // Cancel
+        assertThat(mService.onStopJob(mJobServiceForIdle, mJobParametersForIdle)).isTrue();
+
+        mCancelThread.runActualRunnable();
+
+        // Wait until cancel has set the flag.
+        verify(mDexOptHelper, timeout(TEST_WAIT_TIMEOUT_MS)).controlDexOptBlocking(
+                true);
+
+        mDexOptThread.runActualRunnable();
+
+        // All threads should finish.
+        mDexOptThread.join(TEST_WAIT_TIMEOUT_MS);
+        mCancelThread.join(TEST_WAIT_TIMEOUT_MS);
+
+        // Always reschedule for periodic job
+        verify(mJobServiceForIdle).jobFinished(mJobParametersForIdle, true);
+        verifyLastControlDexOptBlockingCall(false);
+    }
+
+    @Test
+    public void testPeriodicJobCancelLater() throws Exception {
+        initUntilBootCompleted();
+        when(mInjector.createAndStartThread(any(), any())).thenAnswer(
+                i -> createAndStartExecutionThread(i.getArgument(0), i.getArgument(1)));
+
+        // Start and finish post boot job
+        assertThat(mService.onStartJob(mJobServiceForPostBoot, mJobParametersForPostBoot)).isTrue();
+        mDexOptThread.runActualRunnable();
+        mDexOptThread.join(TEST_WAIT_TIMEOUT_MS);
+
+        // Start
+        assertThat(mService.onStartJob(mJobServiceForIdle, mJobParametersForIdle)).isTrue();
+        // Cancel
+        assertThat(mService.onStopJob(mJobServiceForIdle, mJobParametersForIdle)).isTrue();
+
+        // Dexopt thread finishes first.
+        mDexOptThread.runActualRunnable();
+        mDexOptThread.join(TEST_WAIT_TIMEOUT_MS);
+
+        mCancelThread.runActualRunnable();
+        mCancelThread.join(TEST_WAIT_TIMEOUT_MS);
+
+        // Always reschedule for periodic job
+        verify(mJobServiceForIdle).jobFinished(mJobParametersForIdle, true);
+        verify(mDexOptHelper, never()).controlDexOptBlocking(true);
+    }
+
+    @Test
+    public void testStopByThermal() {
+        when(mInjector.createAndStartThread(any(), any())).thenReturn(Thread.currentThread());
+        initUntilBootCompleted();
+
+        assertThat(mService.onStartJob(mJobServiceForPostBoot, mJobParametersForPostBoot)).isTrue();
+
+        ArgumentCaptor<Runnable> argThreadRunnable = ArgumentCaptor.forClass(Runnable.class);
+        verify(mInjector, atLeastOnce()).createAndStartThread(any(), argThreadRunnable.capture());
+
+        // Thermal cancel level
+        when(mInjector.getCurrentThermalStatus()).thenReturn(PowerManager.THERMAL_STATUS_CRITICAL);
+
+        argThreadRunnable.getValue().run();
+
+        verify(mJobServiceForPostBoot).jobFinished(mJobParametersForPostBoot, true);
+        verifyLastControlDexOptBlockingCall(false);
+    }
+
+    @Test
+    public void testRunShellCommandWithInvalidUid() {
+        // Test uid cannot execute the command APIs
+        assertThrows(SecurityException.class, () -> mService.runBackgroundDexoptJob(null));
+    }
+
+    @Test
+    public void testCancelShellCommandWithInvalidUid() {
+        // Test uid cannot execute the command APIs
+        assertThrows(SecurityException.class, () -> mService.cancelBackgroundDexoptJob());
+    }
+
+    private void initUntilBootCompleted() {
+        ArgumentCaptor<BroadcastReceiver> argReceiver = ArgumentCaptor.forClass(
+                BroadcastReceiver.class);
+        ArgumentCaptor<IntentFilter> argIntentFilter = ArgumentCaptor.forClass(IntentFilter.class);
+
+        mService.systemReady();
+
+        verify(mContext).registerReceiver(argReceiver.capture(), argIntentFilter.capture());
+        assertThat(argIntentFilter.getValue().getAction(0)).isEqualTo(Intent.ACTION_BOOT_COMPLETED);
+
+        argReceiver.getValue().onReceive(mContext, null);
+
+        verify(mContext).unregisterReceiver(argReceiver.getValue());
+        ArgumentCaptor<JobInfo> argJobs = ArgumentCaptor.forClass(JobInfo.class);
+        verify(mJobScheduler, times(2)).schedule(argJobs.capture());
+
+        List<Integer> expectedJobIds = Arrays.asList(BackgroundDexOptService.JOB_IDLE_OPTIMIZE,
+                BackgroundDexOptService.JOB_POST_BOOT_UPDATE);
+        List<Integer> jobIds = argJobs.getAllValues().stream().map(job -> job.getId()).collect(
+                Collectors.toList());
+        assertThat(jobIds).containsExactlyElementsIn(expectedJobIds);
+    }
+
+    private void verifyLastControlDexOptBlockingCall(boolean expected) {
+        ArgumentCaptor<Boolean> argDexOptBlock = ArgumentCaptor.forClass(Boolean.class);
+        verify(mDexOptHelper, atLeastOnce()).controlDexOptBlocking(argDexOptBlock.capture());
+        assertThat(argDexOptBlock.getValue()).isEqualTo(expected);
+    }
+
+    private void runFullJob(BackgroundDexOptJobService jobService, JobParameters params,
+            boolean expectedReschedule, int totalJobRuns) {
+        when(mInjector.createAndStartThread(any(), any())).thenReturn(Thread.currentThread());
+        assertThat(mService.onStartJob(jobService, params)).isTrue();
+
+        ArgumentCaptor<Runnable> argThreadRunnable = ArgumentCaptor.forClass(Runnable.class);
+        verify(mInjector, atLeastOnce()).createAndStartThread(any(), argThreadRunnable.capture());
+
+        argThreadRunnable.getValue().run();
+
+        verify(jobService).jobFinished(params, expectedReschedule);
+        // Never block
+        verify(mDexOptHelper, never()).controlDexOptBlocking(true);
+        verifyPerformDexOpt(DEFAULT_PACKAGE_LIST, totalJobRuns);
+    }
+
+    private void verifyPerformDexOpt(ArraySet<String> pkgs, int expectedRuns) {
+        ArgumentCaptor<DexoptOptions> dexOptOptions = ArgumentCaptor.forClass(DexoptOptions.class);
+        verify(mDexOptHelper, atLeastOnce()).performDexOptWithStatus(dexOptOptions.capture());
+        HashMap<String, Integer> primaryPkgs = new HashMap<>(); // K: pkg, V: dexopt runs left
+        for (String pkg : pkgs) {
+            primaryPkgs.put(pkg, expectedRuns);
+        }
+
+        for (DexoptOptions opt : dexOptOptions.getAllValues()) {
+            assertThat(pkgs).contains(opt.getPackageName());
+            assertThat(opt.isDexoptOnlySecondaryDex()).isFalse();
+            Integer count = primaryPkgs.get(opt.getPackageName());
+            assertThat(count).isNotNull();
+            if (count == 1) {
+                primaryPkgs.remove(opt.getPackageName());
+            } else {
+                primaryPkgs.put(opt.getPackageName(), count - 1);
+            }
+        }
+        assertThat(primaryPkgs).isEmpty();
+    }
+
+    private static class StartAndWaitThread extends Thread {
+        private final Runnable mActualRunnable;
+        private final CountDownLatch mLatch = new CountDownLatch(1);
+
+        private StartAndWaitThread(String name, Runnable runnable) {
+            super(name);
+            mActualRunnable = runnable;
+        }
+
+        private void runActualRunnable() {
+            mLatch.countDown();
+        }
+
+        @Override
+        public void run() {
+            // Thread is started but does not run actual code. This is for controlling the execution
+            // order while still meeting Thread.isAlive() check.
+            try {
+                mLatch.await();
+            } catch (InterruptedException e) {
+                throw new RuntimeException(e);
+            }
+            mActualRunnable.run();
+        }
+    }
+
+    private Thread createAndStartExecutionThread(String name, Runnable runnable) {
+        final boolean isDexOptThread = !name.equals("DexOptCancel");
+        StartAndWaitThread thread = new StartAndWaitThread(name, runnable);
+        if (isDexOptThread) {
+            mDexOptThread = thread;
+        } else {
+            mCancelThread = thread;
+        }
+        thread.start();
+        return thread;
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt
index bbfa461..cfc81e6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceHibernationTests.kt
@@ -29,6 +29,7 @@
 import com.android.server.apphibernation.AppHibernationService
 import com.android.server.extendedtestutils.wheneverStatic
 import com.android.server.testutils.whenever
+import org.junit.Assert
 import org.junit.Assert.assertFalse
 import org.junit.Assert.assertTrue
 import org.junit.Before
@@ -36,7 +37,6 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
-import org.mockito.Mockito
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
@@ -102,9 +102,10 @@
         val pm = createPackageManagerService()
         rule.system().validateFinalState()
 
-        pm.setPackageStoppedState(TEST_PACKAGE_NAME, true, TEST_USER_ID)
         TestableLooper.get(this).processAllMessages()
-        Mockito.clearInvocations(appHibernationManager)
+
+        whenever(appHibernationManager.isHibernatingForUser(TEST_PACKAGE_NAME, TEST_USER_ID))
+            .thenReturn(true)
 
         pm.setPackageStoppedState(TEST_PACKAGE_NAME, false, TEST_USER_ID)
 
@@ -115,6 +116,31 @@
     }
 
     @Test
+    fun testExitForceStop_nonExistingAppHibernationManager_doesNotThrowException() {
+        whenever(rule.mocks().injector.getLocalService(AppHibernationManagerInternal::class.java))
+            .thenReturn(null)
+
+        rule.system().stageScanExistingPackage(
+            TEST_PACKAGE_NAME,
+            1L,
+            rule.system().dataAppDirectory)
+        val pm = createPackageManagerService()
+        rule.system().validateFinalState()
+
+        TestableLooper.get(this).processAllMessages()
+
+        whenever(appHibernationManager.isHibernatingForUser(TEST_PACKAGE_NAME, TEST_USER_ID))
+            .thenReturn(true)
+
+        try {
+            pm.setPackageStoppedState(TEST_PACKAGE_NAME, false, TEST_USER_ID)
+            TestableLooper.get(this).processAllMessages()
+        } catch (e: Exception) {
+            Assert.fail("Method throws exception when AppHibernationManager is not ready.\n$e")
+        }
+    }
+
+    @Test
     fun testGetOptimizablePackages_ExcludesGloballyHibernatingPackages() {
         rule.system().stageScanExistingPackage(
             TEST_PACKAGE_NAME,
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageSessionVerifierTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageSessionVerifierTest.java
index 1e399ff..cf5967e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageSessionVerifierTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageSessionVerifierTest.java
@@ -21,6 +21,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -77,18 +78,26 @@
     public void checkRollbacks() throws Exception {
         StagingManager.StagedSession session1 = createStagedSession(111, "com.foo", 1);
         StagingManager.StagedSession session2 = createStagedSession(222, "com.bar", 2);
+        StagingManager.StagedSession session3 = createStagedSession(333, "com.baz", 3);
         session2.sessionParams().setInstallReason(PackageManager.INSTALL_REASON_ROLLBACK);
+        session3.sessionParams().setInstallReason(PackageManager.INSTALL_REASON_ROLLBACK);
+        when(session2.isDestroyed()).thenReturn(true);
         mSessionVerifier.storeSession(session1);
         mSessionVerifier.storeSession(session2);
+        mSessionVerifier.storeSession(session3);
+
+        // Non-rollback session shouldn't be failed by a destroyed session
+        mSessionVerifier.checkRollbacks(session2);
+        verify(session1, never()).setSessionFailed(anyInt(), anyString());
 
         // Non-rollback session should fail
-        mSessionVerifier.checkRollbacks(session2);
+        mSessionVerifier.checkRollbacks(session3);
         verify(session1, times(1)).setSessionFailed(anyInt(), anyString());
 
         // Yet another non-rollback session should fail
-        StagingManager.StagedSession session3 = createStagedSession(333, "com.baz", 3);
+        StagingManager.StagedSession session4 = createStagedSession(444, "com.fur", 4);
         assertThrows(PackageManagerException.class,
-                () -> mSessionVerifier.checkRollbacks(session3));
+                () -> mSessionVerifier.checkRollbacks(session4));
     }
 
     @Test
@@ -105,6 +114,11 @@
         StagingManager.StagedSession session3 = createStagedSession(333, "com.foo", 3);
         assertThrows(PackageManagerException.class,
                 () -> mSessionVerifier.checkOverlaps(session3, session3));
+        // session4 is earlier than session1, but it shouldn't fail session1
+        StagingManager.StagedSession session4 = createStagedSession(444, "com.foo", 0);
+        when(session4.isDestroyed()).thenReturn(true);
+        mSessionVerifier.checkOverlaps(session4, session4);
+        verify(session1, never()).setSessionFailed(anyInt(), anyString());
     }
 
     private PackageInstallerSession createSession(boolean isStaged, boolean isApex,
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index ba580ec..e3c60fd 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -108,6 +108,7 @@
 
     data: [
         ":JobTestApp",
+        ":StubTestApp",
     ],
 
     java_resources: [
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index 5a0f1ee..4c638d6 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -28,6 +28,17 @@
         <option name="test-file-name" value="SimpleServiceTestApp3.apk" />
     </target_preparer>
 
+    <!-- Create place to store apks -->
+    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+        <option name="run-command" value="mkdir -p /data/local/tmp/servicestests" />
+        <option name="teardown-command" value="rm -rf /data/local/tmp/servicestests"/>
+    </target_preparer>
+
+    <!-- Load additional APKs onto device -->
+    <target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
+        <option name="push" value="StubTestApp.apk->/data/local/tmp/servicestests/StubTestApp.apk"/>
+    </target_preparer>
+
     <option name="test-tag" value="FrameworksServicesTests" />
     <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
         <option name="package" value="com.android.frameworks.servicestests" />
diff --git a/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java b/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java
index 3ace3f4..a1d4c20 100644
--- a/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java
+++ b/services/tests/servicestests/src/com/android/server/BluetoothAirplaneModeListenerTest.java
@@ -66,7 +66,7 @@
         when(mHelper.isBluetoothOn()).thenReturn(true);
         Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
 
-        when(mHelper.isA2dpOrHearingAidConnected()).thenReturn(true);
+        when(mHelper.isMediaProfileConnected()).thenReturn(true);
         Assert.assertFalse(mBluetoothAirplaneModeListener.shouldSkipAirplaneModeChange());
 
         when(mHelper.isAirplaneModeOn()).thenReturn(true);
@@ -83,7 +83,7 @@
     public void testHandleAirplaneModeChange_NotInvokeAirplaneModeChanged_NotPopToast() {
         mBluetoothAirplaneModeListener.mToastCount = BluetoothAirplaneModeListener.MAX_TOAST_COUNT;
         when(mHelper.isBluetoothOn()).thenReturn(true);
-        when(mHelper.isA2dpOrHearingAidConnected()).thenReturn(true);
+        when(mHelper.isMediaProfileConnected()).thenReturn(true);
         when(mHelper.isAirplaneModeOn()).thenReturn(true);
         mBluetoothAirplaneModeListener.handleAirplaneModeChange();
 
@@ -97,7 +97,7 @@
     public void testHandleAirplaneModeChange_NotInvokeAirplaneModeChanged_PopToast() {
         mBluetoothAirplaneModeListener.mToastCount = 0;
         when(mHelper.isBluetoothOn()).thenReturn(true);
-        when(mHelper.isA2dpOrHearingAidConnected()).thenReturn(true);
+        when(mHelper.isMediaProfileConnected()).thenReturn(true);
         when(mHelper.isAirplaneModeOn()).thenReturn(true);
         mBluetoothAirplaneModeListener.handleAirplaneModeChange();
 
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
index 086e3c0..a83d51b 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
@@ -68,6 +68,7 @@
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.accessibilityservice.AccessibilityTrace;
 import android.accessibilityservice.IAccessibilityServiceClient;
+import android.accessibilityservice.MagnificationConfig;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -650,8 +651,12 @@
         final float scale = 1.8f;
         final float centerX = 50.5f;
         final float centerY = 100.5f;
-        when(mMockMagnificationProcessor.setScaleAndCenter(displayId,
-                scale, centerX, centerY, true, SERVICE_ID)).thenReturn(true);
+        MagnificationConfig config = new MagnificationConfig.Builder()
+                .setScale(scale)
+                .setCenterX(centerX)
+                .setCenterY(centerY).build();
+        when(mMockMagnificationProcessor.setMagnificationConfig(displayId, config, true,
+                SERVICE_ID)).thenReturn(true);
         when(mMockSecurityPolicy.canControlMagnification(mServiceConnection)).thenReturn(false);
 
         final boolean result = mServiceConnection.setMagnificationScaleAndCenter(
@@ -665,8 +670,12 @@
         final float scale = 1.8f;
         final float centerX = 50.5f;
         final float centerY = 100.5f;
-        when(mMockMagnificationProcessor.setScaleAndCenter(displayId,
-                scale, centerX, centerY, true, SERVICE_ID)).thenReturn(true);
+        MagnificationConfig config = new MagnificationConfig.Builder()
+                .setScale(scale)
+                .setCenterX(centerX)
+                .setCenterY(centerY).build();
+        when(mMockMagnificationProcessor.setMagnificationConfig(displayId, config, true,
+                SERVICE_ID)).thenReturn(true);
         when(mMockSystemSupport.getCurrentUserIdLocked()).thenReturn(USER_ID2);
 
         final boolean result = mServiceConnection.setMagnificationScaleAndCenter(
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
index c412b94..205c3da 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MagnificationProcessorTest.java
@@ -16,25 +16,33 @@
 
 package com.android.server.accessibility;
 
+import static android.accessibilityservice.MagnificationConfig.FULLSCREEN_MODE;
+import static android.accessibilityservice.MagnificationConfig.WINDOW_MODE;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.accessibilityservice.MagnificationConfig;
 import android.graphics.Region;
 
 import com.android.server.accessibility.magnification.FullScreenMagnificationController;
 import com.android.server.accessibility.magnification.MagnificationController;
 import com.android.server.accessibility.magnification.MagnificationProcessor;
+import com.android.server.accessibility.magnification.WindowMagnificationManager;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
-
+import org.mockito.stubbing.Answer;
 
 /**
  * Tests for the {@link MagnificationProcessor}
@@ -42,57 +50,115 @@
 public class MagnificationProcessorTest {
 
     private static final int TEST_DISPLAY = 0;
-
+    private static final int SERVICE_ID = 42;
+    private static final float TEST_SCALE = 1.8f;
+    private static final float TEST_CENTER_X = 50.5f;
+    private static final float TEST_CENTER_Y = 100.5f;
     private MagnificationProcessor mMagnificationProcessor;
     @Mock
     private MagnificationController mMockMagnificationController;
     @Mock
     private FullScreenMagnificationController mMockFullScreenMagnificationController;
+    @Mock
+    private WindowMagnificationManager mMockWindowMagnificationManager;
+    FullScreenMagnificationControllerStub mFullScreenMagnificationControllerStub;
+    WindowMagnificationManagerStub mWindowMagnificationManagerStub;
 
     @Before
+
     public void setup() {
         MockitoAnnotations.initMocks(this);
-
+        mFullScreenMagnificationControllerStub = new FullScreenMagnificationControllerStub(
+                mMockFullScreenMagnificationController);
+        mWindowMagnificationManagerStub = new WindowMagnificationManagerStub(
+                mMockWindowMagnificationManager);
         when(mMockMagnificationController.getFullScreenMagnificationController()).thenReturn(
                 mMockFullScreenMagnificationController);
+        when(mMockMagnificationController.getWindowMagnificationMgr()).thenReturn(
+                mMockWindowMagnificationManager);
         mMagnificationProcessor = new MagnificationProcessor(mMockMagnificationController);
     }
 
     @Test
-    public void getScale() {
-        final float result = 2;
-        when(mMockFullScreenMagnificationController.getScale(TEST_DISPLAY)).thenReturn(result);
+    public void getScale_fullscreenMode_expectedValue() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(FULLSCREEN_MODE)
+                .setScale(TEST_SCALE).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
 
         float scale = mMagnificationProcessor.getScale(TEST_DISPLAY);
 
-        assertEquals(scale, result, 0);
+        assertEquals(scale, TEST_SCALE, 0);
     }
 
     @Test
-    public void getCenterX_canControlMagnification_returnCenterX() {
-        final float result = 200;
-        when(mMockFullScreenMagnificationController.getCenterX(TEST_DISPLAY)).thenReturn(result);
+    public void getScale_windowMode_expectedValue() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(WINDOW_MODE)
+                .setScale(TEST_SCALE).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
+
+        float scale = mMagnificationProcessor.getScale(TEST_DISPLAY);
+
+        assertEquals(scale, TEST_SCALE, 0);
+    }
+
+    @Test
+    public void getCenterX_canControlFullscreenMagnification_returnCenterX() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(FULLSCREEN_MODE)
+                .setCenterX(TEST_CENTER_X).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
 
         float centerX = mMagnificationProcessor.getCenterX(
                 TEST_DISPLAY,  /* canControlMagnification= */true);
 
-        assertEquals(centerX, result, 0);
+        assertEquals(centerX, TEST_CENTER_X, 0);
     }
 
     @Test
-    public void getCenterY_canControlMagnification_returnCenterY() {
-        final float result = 300;
-        when(mMockFullScreenMagnificationController.getCenterY(TEST_DISPLAY)).thenReturn(result);
+    public void getCenterX_canControlWindowMagnification_returnCenterX() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(WINDOW_MODE)
+                .setCenterX(TEST_CENTER_X).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
+
+        float centerX = mMagnificationProcessor.getCenterX(
+                TEST_DISPLAY,  /* canControlMagnification= */true);
+
+        assertEquals(centerX, TEST_CENTER_X, 0);
+    }
+
+    @Test
+    public void getCenterY_canControlFullscreenMagnification_returnCenterY() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(FULLSCREEN_MODE)
+                .setCenterY(TEST_CENTER_Y).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
 
         float centerY = mMagnificationProcessor.getCenterY(
                 TEST_DISPLAY,  /* canControlMagnification= */false);
 
-        assertEquals(centerY, result, 0);
+        assertEquals(centerY, TEST_CENTER_Y, 0);
     }
 
     @Test
-    public void getMagnificationRegion_canControlMagnification_returnRegion() {
+    public void getCenterY_canControlWindowMagnification_returnCenterY() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(WINDOW_MODE)
+                .setCenterY(TEST_CENTER_Y).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
+
+        float centerY = mMagnificationProcessor.getCenterY(
+                TEST_DISPLAY,  /* canControlMagnification= */false);
+
+        assertEquals(centerY, TEST_CENTER_Y, 0);
+    }
+
+    @Test
+    public void getMagnificationRegion_canControlFullscreenMagnification_returnRegion() {
         final Region region = new Region(10, 20, 100, 200);
+        setMagnificationActivated(TEST_DISPLAY, FULLSCREEN_MODE);
         mMagnificationProcessor.getMagnificationRegion(TEST_DISPLAY,
                 region,  /* canControlMagnification= */true);
 
@@ -101,14 +167,25 @@
     }
 
     @Test
-    public void getMagnificationRegion_notRegistered_shouldRegisterThenUnregister() {
+    public void getMagnificationRegion_canControlWindowMagnification_returnRegion() {
         final Region region = new Region(10, 20, 100, 200);
+        setMagnificationActivated(TEST_DISPLAY, WINDOW_MODE);
+        mMagnificationProcessor.getMagnificationRegion(TEST_DISPLAY,
+                region,  /* canControlMagnification= */true);
+
+        verify(mMockWindowMagnificationManager).getMagnificationSourceBounds(eq(TEST_DISPLAY),
+                eq(region));
+    }
+
+    @Test
+    public void getMagnificationRegion_fullscreenModeNotRegistered_shouldRegisterThenUnregister() {
+        final Region region = new Region(10, 20, 100, 200);
+        setMagnificationActivated(TEST_DISPLAY, FULLSCREEN_MODE);
         doAnswer((invocation) -> {
             ((Region) invocation.getArguments()[1]).set(region);
             return null;
         }).when(mMockFullScreenMagnificationController).getMagnificationRegion(eq(TEST_DISPLAY),
                 any());
-        when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
 
         final Region result = new Region();
         mMagnificationProcessor.getMagnificationRegion(TEST_DISPLAY,
@@ -119,44 +196,270 @@
     }
 
     @Test
-    public void getMagnificationCenterX_notRegistered_shouldRegisterThenUnregister() {
-        final float centerX = 480.0f;
-        when(mMockFullScreenMagnificationController.getCenterX(TEST_DISPLAY)).thenReturn(centerX);
-        when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
+    public void getMagnificationCenterX_fullscreenModeNotRegistered_shouldRegisterThenUnregister() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(FULLSCREEN_MODE)
+                .setCenterX(TEST_CENTER_X).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
 
         final float result = mMagnificationProcessor.getCenterX(
                 TEST_DISPLAY,  /* canControlMagnification= */ true);
-        assertEquals(centerX, result, 0);
+        assertEquals(TEST_CENTER_X, result, 0);
         verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
         verify(mMockFullScreenMagnificationController).unregister(TEST_DISPLAY);
     }
 
     @Test
-    public void getMagnificationCenterY_notRegistered_shouldRegisterThenUnregister() {
-        final float centerY = 640.0f;
-        when(mMockFullScreenMagnificationController.getCenterY(TEST_DISPLAY)).thenReturn(centerY);
-        when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
+    public void getMagnificationCenterY_fullscreenModeNotRegistered_shouldRegisterThenUnregister() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(FULLSCREEN_MODE)
+                .setCenterY(TEST_CENTER_Y).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
 
         final float result = mMagnificationProcessor.getCenterY(
                 TEST_DISPLAY,  /* canControlMagnification= */ true);
-        assertEquals(centerY, result, 0);
+        assertEquals(TEST_CENTER_Y, result, 0);
         verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
         verify(mMockFullScreenMagnificationController).unregister(TEST_DISPLAY);
     }
 
     @Test
-    public void setMagnificationScaleAndCenter_notRegistered_shouldRegister() {
-        final int serviceId = 42;
-        final float scale = 1.8f;
-        final float centerX = 50.5f;
-        final float centerY = 100.5f;
-        when(mMockFullScreenMagnificationController.setScaleAndCenter(TEST_DISPLAY,
-                scale, centerX, centerY, true, serviceId)).thenReturn(true);
-        when(mMockFullScreenMagnificationController.isRegistered(TEST_DISPLAY)).thenReturn(false);
+    public void getCurrentMode_configDefaultMode_returnActivatedMode() {
+        final int targetMode = WINDOW_MODE;
+        setMagnificationActivated(TEST_DISPLAY, targetMode);
 
-        final boolean result = mMagnificationProcessor.setScaleAndCenter(
-                TEST_DISPLAY, scale, centerX, centerY, true, serviceId);
+        int currentMode = mMagnificationProcessor.getControllingMode(TEST_DISPLAY);
+
+        assertEquals(WINDOW_MODE, currentMode);
+    }
+
+    @Test
+    public void reset_fullscreenMagnificationActivated() {
+        setMagnificationActivated(TEST_DISPLAY, FULLSCREEN_MODE);
+
+        mMagnificationProcessor.reset(TEST_DISPLAY, /* animate= */false);
+
+        verify(mMockFullScreenMagnificationController).reset(TEST_DISPLAY, false);
+    }
+
+    @Test
+    public void reset_windowMagnificationActivated() {
+        setMagnificationActivated(TEST_DISPLAY, WINDOW_MODE);
+
+        mMagnificationProcessor.reset(TEST_DISPLAY, /* animate= */false);
+
+        verify(mMockWindowMagnificationManager).reset(TEST_DISPLAY);
+    }
+
+    @Test
+    public void setMagnificationConfig_fullscreenModeNotRegistered_shouldRegister() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(FULLSCREEN_MODE)
+                .setScale(TEST_SCALE)
+                .setCenterX(TEST_CENTER_X)
+                .setCenterY(TEST_CENTER_Y).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
+
+        final boolean result = mMagnificationProcessor.setMagnificationConfig(
+                TEST_DISPLAY, config, true, SERVICE_ID);
         assertTrue(result);
         verify(mMockFullScreenMagnificationController).register(TEST_DISPLAY);
     }
+
+    @Test
+    public void setMagnificationConfig_windowMode_enableMagnification() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(WINDOW_MODE)
+                .setScale(TEST_SCALE)
+                .setCenterX(TEST_CENTER_X)
+                .setCenterY(TEST_CENTER_Y).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
+
+        final boolean result = mMagnificationProcessor.setMagnificationConfig(
+                TEST_DISPLAY, config, true, SERVICE_ID);
+
+        assertTrue(result);
+    }
+
+    @Test
+    public void setMagnificationConfig_fullscreenEnabled_expectedConfigValues() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(FULLSCREEN_MODE)
+                .setScale(TEST_SCALE)
+                .setCenterX(TEST_CENTER_X)
+                .setCenterY(TEST_CENTER_Y).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
+     //   mMockFullScreenMagnificationController.unregister(TEST_DISPLAY);
+        mMagnificationProcessor.setMagnificationConfig(
+                TEST_DISPLAY, config, true, SERVICE_ID);
+
+        final MagnificationConfig result = mMagnificationProcessor.getMagnificationConfig(
+                TEST_DISPLAY);
+
+        assertConfigEquals(config, result);
+    }
+
+    @Test
+    public void setMagnificationConfig_windowEnabled_expectedConfigValues() {
+        final MagnificationConfig config = new MagnificationConfig.Builder()
+                .setMode(WINDOW_MODE)
+                .setScale(TEST_SCALE)
+                .setCenterX(TEST_CENTER_X)
+                .setCenterY(TEST_CENTER_Y).build();
+        setMagnificationActivated(TEST_DISPLAY, config);
+
+        mMagnificationProcessor.setMagnificationConfig(
+                TEST_DISPLAY, config, true, SERVICE_ID);
+
+        final MagnificationConfig result = mMagnificationProcessor.getMagnificationConfig(
+                TEST_DISPLAY);
+
+        assertConfigEquals(config, result);
+    }
+
+    @Test
+    public void setMagnificationConfig_controllingModeChangeAndAnimating_transitionConfigMode() {
+        final int currentActivatedMode = WINDOW_MODE;
+        final int targetMode = FULLSCREEN_MODE;
+        final MagnificationConfig oldConfig = new MagnificationConfig.Builder()
+                .setMode(currentActivatedMode)
+                .setScale(TEST_SCALE)
+                .setCenterX(TEST_CENTER_X)
+                .setCenterY(TEST_CENTER_Y).build();
+        setMagnificationActivated(TEST_DISPLAY, oldConfig);
+        final MagnificationConfig newConfig = new MagnificationConfig.Builder()
+                .setMode(targetMode)
+                .setScale(TEST_SCALE)
+                .setCenterX(TEST_CENTER_X + 10)
+                .setCenterY(TEST_CENTER_Y + 10).build();
+
+        // Has magnification animation running
+        when(mMockMagnificationController.hasDisableMagnificationCallback(TEST_DISPLAY)).thenReturn(
+                true);
+        setMagnificationActivated(TEST_DISPLAY, newConfig);
+
+        final MagnificationConfig result = mMagnificationProcessor.getMagnificationConfig(
+                TEST_DISPLAY);
+        verify(mMockMagnificationController).transitionMagnificationConfigMode(eq(TEST_DISPLAY),
+                eq(newConfig), anyBoolean());
+        assertConfigEquals(newConfig, result);
+    }
+
+    private void setMagnificationActivated(int displayId, int configMode) {
+        setMagnificationActivated(displayId,
+                new MagnificationConfig.Builder().setMode(configMode).build());
+    }
+
+    private void setMagnificationActivated(int displayId, MagnificationConfig config) {
+        when(mMockMagnificationController.isActivated(displayId, config.getMode())).thenReturn(
+                true);
+        mMagnificationProcessor.setMagnificationConfig(displayId, config, false, SERVICE_ID);
+        if (config.getMode() == FULLSCREEN_MODE) {
+            when(mMockMagnificationController.isActivated(displayId, WINDOW_MODE)).thenReturn(
+                    false);
+            mFullScreenMagnificationControllerStub.resetAndStubMethods();
+            mMockFullScreenMagnificationController.setScaleAndCenter(displayId, config.getScale(),
+                    config.getCenterX(), config.getCenterY(), true, SERVICE_ID);
+        } else if (config.getMode() == WINDOW_MODE) {
+            when(mMockMagnificationController.isActivated(displayId, FULLSCREEN_MODE)).thenReturn(
+                    false);
+            mWindowMagnificationManagerStub.resetAndStubMethods();
+            mMockWindowMagnificationManager.enableWindowMagnification(displayId, config.getScale(),
+                    config.getCenterX(), config.getCenterY());
+        }
+    }
+
+    private void assertConfigEquals(MagnificationConfig expected, MagnificationConfig actual) {
+        assertEquals(expected.getMode(), actual.getMode());
+        assertEquals(expected.getScale(), actual.getScale(), 0);
+        assertEquals(expected.getCenterX(), actual.getCenterX(), 0);
+        assertEquals(expected.getCenterY(), actual.getCenterY(), 0);
+    }
+
+    private static class FullScreenMagnificationControllerStub {
+        private final FullScreenMagnificationController mScreenMagnificationController;
+        private float mScale = 1.0f;
+        private float mCenterX = 0;
+        private float mCenterY = 0;
+        private boolean mIsRegistered = false;
+
+        FullScreenMagnificationControllerStub(
+                FullScreenMagnificationController screenMagnificationController) {
+            mScreenMagnificationController = screenMagnificationController;
+        }
+
+        private void stubMethods() {
+            doAnswer(invocation -> mScale).when(mScreenMagnificationController).getScale(
+                    TEST_DISPLAY);
+            doAnswer(invocation -> mCenterX).when(mScreenMagnificationController).getCenterX(
+                    TEST_DISPLAY);
+            doAnswer(invocation -> mCenterY).when(mScreenMagnificationController).getCenterY(
+                    TEST_DISPLAY);
+            doAnswer(invocation -> mIsRegistered).when(mScreenMagnificationController).isRegistered(
+                    TEST_DISPLAY);
+            Answer enableMagnificationStubAnswer = invocation -> {
+                mScale = invocation.getArgument(1);
+                mCenterX = invocation.getArgument(2);
+                mCenterY = invocation.getArgument(3);
+                return true;
+            };
+            doAnswer(enableMagnificationStubAnswer).when(
+                    mScreenMagnificationController).setScaleAndCenter(eq(TEST_DISPLAY), anyFloat(),
+                    anyFloat(), anyFloat(), eq(true), eq(SERVICE_ID));
+
+            Answer registerStubAnswer = invocation -> {
+                mIsRegistered = true;
+                return true;
+            };
+            doAnswer(registerStubAnswer).when(
+                    mScreenMagnificationController).register(eq(TEST_DISPLAY));
+
+            Answer unregisterStubAnswer = invocation -> {
+                mIsRegistered = false;
+                return true;
+            };
+            doAnswer(unregisterStubAnswer).when(
+                    mScreenMagnificationController).unregister(eq(TEST_DISPLAY));
+        }
+
+        public void resetAndStubMethods() {
+            Mockito.reset(mScreenMagnificationController);
+            stubMethods();
+        }
+    }
+
+    private static class WindowMagnificationManagerStub {
+        private final WindowMagnificationManager mWindowMagnificationManager;
+        private float mScale = 1.0f;
+        private float mCenterX = 0;
+        private float mCenterY = 0;
+
+        WindowMagnificationManagerStub(
+                WindowMagnificationManager windowMagnificationManager) {
+            mWindowMagnificationManager = windowMagnificationManager;
+        }
+
+        private void stubMethods() {
+            doAnswer(invocation -> mScale).when(mWindowMagnificationManager).getScale(
+                    TEST_DISPLAY);
+            doAnswer(invocation -> mCenterX).when(mWindowMagnificationManager).getCenterX(
+                    TEST_DISPLAY);
+            doAnswer(invocation -> mCenterY).when(mWindowMagnificationManager).getCenterY(
+                    TEST_DISPLAY);
+            Answer enableWindowMagnificationStubAnswer = invocation -> {
+                mScale = invocation.getArgument(1);
+                mCenterX = invocation.getArgument(2);
+                mCenterY = invocation.getArgument(3);
+                return true;
+            };
+            doAnswer(enableWindowMagnificationStubAnswer).when(
+                    mWindowMagnificationManager).enableWindowMagnification(eq(TEST_DISPLAY),
+                    anyFloat(), anyFloat(), anyFloat());
+        }
+
+        public void resetAndStubMethods() {
+            Mockito.reset(mWindowMagnificationManager);
+            stubMethods();
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
index 8a521d8..ec1a0c2 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MagnificationControllerTest.java
@@ -38,6 +38,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.accessibilityservice.MagnificationConfig;
 import android.content.Context;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -154,7 +155,7 @@
         verify(mScreenMagnificationController, never()).reset(anyInt(),
                 any(MagnificationAnimationCallback.class));
         verify(mMockConnection.getConnection(), never()).enableWindowMagnification(anyInt(),
-                anyFloat(), anyFloat(), anyFloat(),
+                anyFloat(), anyFloat(), anyFloat(), anyFloat(), anyFloat(),
                 nullable(IRemoteMagnificationAnimationCallback.class));
     }
 
@@ -229,7 +230,7 @@
     }
 
     @Test
-    public void transitionToFullScreen_centerNotInTheBounds_magnifyTheCenterOfMagnificationBounds()
+    public void transitionToFullScreen_centerNotInTheBounds_magnifyBoundsCenter()
             throws RemoteException {
         final Rect magnificationBounds = MAGNIFICATION_REGION.getBounds();
         final PointF magnifiedCenter = new PointF(magnificationBounds.right + 100,
@@ -289,6 +290,73 @@
     }
 
     @Test
+    public void configTransitionToWindowMode_fullScreenMagnifying_disableFullScreenAndEnableWindow()
+            throws RemoteException {
+        activateMagnifier(MODE_FULLSCREEN, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
+
+        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
+                obtainMagnificationConfig(MODE_WINDOW),
+                false);
+
+        verify(mScreenMagnificationController).reset(eq(TEST_DISPLAY), eq(false));
+        mMockConnection.invokeCallbacks();
+        assertEquals(MAGNIFIED_CENTER_X, mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 0);
+        assertEquals(MAGNIFIED_CENTER_Y, mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 0);
+    }
+
+    @Test
+    public void configTransitionToFullScreen_windowMagnifying_disableWindowAndEnableFullScreen()
+            throws RemoteException {
+        final boolean animate = true;
+        activateMagnifier(MODE_WINDOW, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
+        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
+                obtainMagnificationConfig(MODE_FULLSCREEN),
+                animate);
+        mMockConnection.invokeCallbacks();
+
+        assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY));
+        verify(mScreenMagnificationController).setScaleAndCenter(TEST_DISPLAY,
+                DEFAULT_SCALE, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y,
+                animate, MAGNIFICATION_GESTURE_HANDLER_ID);
+    }
+
+    @Test
+    public void configTransitionToFullScreen_userSettingsDisablingFullScreen_enableFullScreen()
+            throws RemoteException {
+        activateMagnifier(MODE_FULLSCREEN, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
+        // User-setting mode
+        mMagnificationController.transitionMagnificationModeLocked(TEST_DISPLAY,
+                MODE_WINDOW, mTransitionCallBack);
+
+        // Config-setting mode
+        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
+                obtainMagnificationConfig(MODE_FULLSCREEN),
+                true);
+
+        assertEquals(DEFAULT_SCALE, mScreenMagnificationController.getScale(TEST_DISPLAY), 0);
+        assertEquals(MAGNIFIED_CENTER_X, mScreenMagnificationController.getCenterX(TEST_DISPLAY),
+                0);
+        assertEquals(MAGNIFIED_CENTER_Y, mScreenMagnificationController.getCenterY(TEST_DISPLAY),
+                0);
+    }
+
+    @Test
+    public void interruptDuringTransitionToWindow_disablingFullScreen_discardPreviousTransition()
+            throws RemoteException {
+        activateMagnifier(MODE_FULLSCREEN, MAGNIFIED_CENTER_X, MAGNIFIED_CENTER_Y);
+        // User-setting mode
+        mMagnificationController.transitionMagnificationModeLocked(TEST_DISPLAY,
+                MODE_WINDOW, mTransitionCallBack);
+
+        // Config-setting mode
+        mMagnificationController.transitionMagnificationConfigMode(TEST_DISPLAY,
+                obtainMagnificationConfig(MODE_FULLSCREEN),
+                true);
+
+        verify(mTransitionCallBack, never()).onResult(TEST_DISPLAY, true);
+    }
+
+    @Test
     public void onDisplayRemoved_notifyAllModules() {
         mMagnificationController.onDisplayRemoved(TEST_DISPLAY);
 
@@ -402,6 +470,16 @@
     }
 
     @Test
+    public void onFullScreenMagnificationActivationState_windowActivated_disableMagnification()
+            throws RemoteException {
+        setMagnificationEnabled(MODE_WINDOW);
+
+        mMagnificationController.onFullScreenMagnificationActivationState(TEST_DISPLAY, true);
+
+        verify(mWindowMagnificationManager).disableWindowMagnification(eq(TEST_DISPLAY), eq(false));
+    }
+
+    @Test
     public void onTouchInteractionStart_fullScreenAndCapabilitiesAll_showMagnificationButton()
             throws RemoteException {
         setMagnificationEnabled(MODE_FULLSCREEN);
@@ -609,6 +687,10 @@
     private void setMagnificationEnabled(int mode, float centerX, float centerY)
             throws RemoteException {
         setMagnificationModeSettings(mode);
+        activateMagnifier(mode, centerX, centerY);
+    }
+
+    private void activateMagnifier(int mode, float centerX, float centerY) throws RemoteException {
         mScreenMagnificationControllerStubber.resetAndStubMethods();
         final boolean windowMagnifying = mWindowMagnificationManager.isWindowMagnifierEnabled(
                 TEST_DISPLAY);
@@ -631,6 +713,11 @@
                 Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, mode, CURRENT_USER_ID);
     }
 
+    private MagnificationConfig obtainMagnificationConfig(int mode) {
+        return new MagnificationConfig.Builder().setMode(mode).setScale(DEFAULT_SCALE).setCenterX(
+                MAGNIFIED_CENTER_X).setCenterY(MAGNIFIED_CENTER_Y).build();
+    }
+
     /**
      * Stubs public methods to simulate the real beahviours.
      */
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java
index 2a53504..0659a60 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/MockWindowMagnificationConnection.java
@@ -93,7 +93,7 @@
             final float scale = invocation.getArgument(1);
             mScale = Float.isNaN(scale) ? mScale : scale;
             computeMirrorWindowFrame(invocation.getArgument(2), invocation.getArgument(3));
-            setAnimationCallback(invocation.getArgument(4));
+            setAnimationCallback(invocation.getArgument(6));
             computeSourceBounds();
             mHasPendingCallback = true;
             if (!mSuspendCallback) {
@@ -101,7 +101,7 @@
             }
             return null;
         }).when(mConnection).enableWindowMagnification(anyInt(), anyFloat(), anyFloat(), anyFloat(),
-                nullable(IRemoteMagnificationAnimationCallback.class));
+                anyFloat(), anyFloat(), nullable(IRemoteMagnificationAnimationCallback.class));
     }
 
     private void stubDisableWindowMagnification() throws RemoteException {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java
index 1638563..3822dc3 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationConnectionWrapperTest.java
@@ -67,7 +67,7 @@
     @Test
     public void enableWindowMagnification() throws RemoteException {
         mConnectionWrapper.enableWindowMagnification(TEST_DISPLAY, 2, 100f, 200f,
-                mAnimationCallback);
+                0f, 0f, mAnimationCallback);
 
         verify(mAnimationCallback).onResult(true);
     }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
index 1b8aff5..b807c11 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationGestureHandlerTest.java
@@ -24,6 +24,7 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.testing.TestableContext;
 import android.util.DebugUtils;
 import android.view.InputDevice;
@@ -58,10 +59,11 @@
     public static final int STATE_SHOW_MAGNIFIER_SHORTCUT = 2;
     public static final int STATE_TWO_FINGERS_DOWN = 3;
     public static final int STATE_SHOW_MAGNIFIER_TRIPLE_TAP = 4;
+    public static final int STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD = 5;
     //TODO: Test it after can injecting Handler to GestureMatcher is available.
 
     public static final int FIRST_STATE = STATE_IDLE;
-    public static final int LAST_STATE = STATE_SHOW_MAGNIFIER_TRIPLE_TAP;
+    public static final int LAST_STATE = STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD;
 
     // Co-prime x and y, to potentially catch x-y-swapped errors
     public static final float DEFAULT_TAP_X = 301;
@@ -178,6 +180,12 @@
                         == mWindowMagnificationGestureHandler.mDetectingState, state);
             }
                 break;
+            case STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
+                check(isWindowMagnifierEnabled(DISPLAY_0), state);
+                check(mWindowMagnificationGestureHandler.mCurrentState
+                        == mWindowMagnificationGestureHandler.mViewportDraggingState, state);
+            }
+            break;
             case STATE_TWO_FINGERS_DOWN: {
                 check(isWindowMagnifierEnabled(DISPLAY_0), state);
                 check(mWindowMagnificationGestureHandler.mCurrentState
@@ -229,6 +237,13 @@
                     tap();
                 }
                 break;
+                case STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
+                    // Perform triple tap and hold gesture
+                    tap();
+                    tap();
+                    tapAndHold();
+                }
+                break;
                 default:
                     throw new IllegalArgumentException("Illegal state: " + state);
             }
@@ -262,6 +277,10 @@
                 tap();
             }
             break;
+            case STATE_SHOW_MAGNIFIER_TRIPLE_TAP_AND_HOLD: {
+                send(upEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
+            }
+            break;
             default:
                 throw new IllegalArgumentException("Illegal state: " + state);
         }
@@ -308,6 +327,11 @@
         send(upEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
     }
 
+    private void tapAndHold() {
+        send(downEvent(DEFAULT_TAP_X, DEFAULT_TAP_Y));
+        SystemClock.sleep(ViewConfiguration.getLongPressTimeout() + 100);
+    }
+
     private String stateDump() {
         return "\nCurrent state dump:\n" + mWindowMagnificationGestureHandler.mCurrentState;
     }
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
index 15ba358..85512f3 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/WindowMagnificationManagerTest.java
@@ -143,8 +143,7 @@
      * new connection.
      */
     @Test
-    public void
-            setSecondConnectionAndFormerConnectionBinderDead_hasWrapperAndNotCallUnlinkToDeath()
+    public void setSecondConnectionAndFormerConnectionBinderDead_hasWrapperAndNotCallUnlinkToDeath()
             throws RemoteException {
         mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
         MockWindowMagnificationConnection secondConnection =
@@ -177,7 +176,7 @@
         mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 2f, 200f, 300f);
 
         verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(2f),
-                eq(200f), eq(300f), notNull());
+                eq(200f), eq(300f), eq(0f), eq(0f), notNull());
     }
 
     @Test
@@ -189,7 +188,8 @@
                 mAnimationCallback);
 
         verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(2f),
-                eq(200f), eq(300f), any(IRemoteMagnificationAnimationCallback.class));
+                eq(200f), eq(300f), eq(0f), eq(0f),
+                any(IRemoteMagnificationAnimationCallback.class));
         verify(mAnimationCallback).onResult(true);
     }
 
@@ -377,6 +377,17 @@
     }
 
     @Test
+    public void resetMagnification_enabled_windowMagnifierDisabled() {
+        mWindowMagnificationManager.setConnection(mMockConnection.getConnection());
+        mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, NaN, NaN);
+        assertTrue(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY));
+
+        mWindowMagnificationManager.reset(TEST_DISPLAY);
+
+        assertFalse(mWindowMagnificationManager.isWindowMagnifierEnabled(TEST_DISPLAY));
+    }
+
+    @Test
     public void onScreenOff_windowMagnifierIsEnabled_removeButtonAndDisableWindowMagnification()
             throws RemoteException {
         mWindowMagnificationManager.requestConnection(true);
@@ -400,6 +411,34 @@
     }
 
     @Test
+    public void centerGetter_enabledOnTestDisplayWindowAtCenter_expectedValues()
+            throws RemoteException {
+        mWindowMagnificationManager.requestConnection(true);
+        mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f,
+                100f, 200f, WindowMagnificationManager.WINDOW_POSITION_AT_CENTER);
+
+        assertEquals(mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 100f);
+        assertEquals(mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 200f);
+
+        verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(3f),
+                eq(100f), eq(200f), eq(0f), eq(0f), notNull());
+    }
+
+    @Test
+    public void centerGetter_enabledOnTestDisplayWindowAtLeftTop_expectedValues()
+            throws RemoteException {
+        mWindowMagnificationManager.requestConnection(true);
+        mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f,
+                100f, 200f, WindowMagnificationManager.WINDOW_POSITION_AT_TOP_LEFT);
+
+        assertEquals(mWindowMagnificationManager.getCenterX(TEST_DISPLAY), 100f);
+        assertEquals(mWindowMagnificationManager.getCenterY(TEST_DISPLAY), 200f);
+
+        verify(mMockConnection.getConnection()).enableWindowMagnification(eq(TEST_DISPLAY), eq(3f),
+                eq(100f), eq(200f), eq(-1f), eq(-1f), notNull());
+    }
+
+    @Test
     public void onDisplayRemoved_enabledOnTestDisplay_disabled() {
         mWindowMagnificationManager.requestConnection(true);
         mWindowMagnificationManager.enableWindowMagnification(TEST_DISPLAY, 3f, 100f, 200f);
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 9ffb5017..f1a63bc 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -21,6 +21,7 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
+import static com.android.server.am.UserController.COMPLETE_USER_SWITCH_MSG;
 import static com.android.server.am.UserController.CONTINUE_USER_SWITCH_MSG;
 import static com.android.server.am.UserController.REPORT_LOCKED_BOOT_COMPLETE_MSG;
 import static com.android.server.am.UserController.REPORT_USER_SWITCH_COMPLETE_MSG;
@@ -59,6 +60,7 @@
 import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.IUserSwitchObserver;
+import android.app.KeyguardManager;
 import android.content.Context;
 import android.content.IIntentReceiver;
 import android.content.Intent;
@@ -325,8 +327,16 @@
         assertWithMessage("No messages should be sent").that(actualCodes).isEmpty();
     }
 
+    private void continueAndCompleteUserSwitch(UserState userState, int oldUserId, int newUserId) {
+        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
+        mInjector.mHandler.removeMessages(UserController.COMPLETE_USER_SWITCH_MSG);
+        mUserController.completeUserSwitch(newUserId);
+    }
+
     @Test
     public void testContinueUserSwitch() throws RemoteException {
+        mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
         // Start user -- this will update state of mUserController
         mUserController.startUser(TEST_USER_ID, true);
         Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
@@ -336,7 +346,28 @@
         int newUserId = reportMsg.arg2;
         mInjector.mHandler.clearAllRecordedMessages();
         // Verify that continueUserSwitch worked as expected
-        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
+        continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
+        verify(mInjector, times(0)).dismissKeyguard(any(), anyString());
+        verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
+        continueUserSwitchAssertions(TEST_USER_ID, false);
+    }
+
+    @Test
+    public void testContinueUserSwitchDismissKeyguard() throws RemoteException {
+        when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(false);
+        mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
+                /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false);
+        // Start user -- this will update state of mUserController
+        mUserController.startUser(TEST_USER_ID, true);
+        Message reportMsg = mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG);
+        assertNotNull(reportMsg);
+        UserState userState = (UserState) reportMsg.obj;
+        int oldUserId = reportMsg.arg1;
+        int newUserId = reportMsg.arg2;
+        mInjector.mHandler.clearAllRecordedMessages();
+        // Verify that continueUserSwitch worked as expected
+        continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
+        verify(mInjector, times(1)).dismissKeyguard(any(), anyString());
         verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
         continueUserSwitchAssertions(TEST_USER_ID, false);
     }
@@ -355,7 +386,7 @@
         int newUserId = reportMsg.arg2;
         mInjector.mHandler.clearAllRecordedMessages();
         // Verify that continueUserSwitch worked as expected
-        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
+        continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
         verify(mInjector.getWindowManager(), never()).stopFreezingScreen();
         continueUserSwitchAssertions(TEST_USER_ID, false);
     }
@@ -363,6 +394,7 @@
     private void continueUserSwitchAssertions(int expectedUserId, boolean backgroundUserStopping)
             throws RemoteException {
         Set<Integer> expectedCodes = new LinkedHashSet<>();
+        expectedCodes.add(COMPLETE_USER_SWITCH_MSG);
         expectedCodes.add(REPORT_USER_SWITCH_COMPLETE_MSG);
         if (backgroundUserStopping) {
             expectedCodes.add(0); // this is for directly posting in stopping.
@@ -397,7 +429,7 @@
     }
 
     @Test
-    public void testExplicitSystenUserStartInBackground() {
+    public void testExplicitSystemUserStartInBackground() {
         setUpUser(UserHandle.USER_SYSTEM, 0);
         assertFalse(mUserController.isSystemUserStarted());
         assertTrue(mUserController.startUser(UserHandle.USER_SYSTEM, false, null));
@@ -646,7 +678,7 @@
         mUserStates.put(newUserId, userState);
         mInjector.mHandler.clearAllRecordedMessages();
         // Verify that continueUserSwitch worked as expected
-        mUserController.continueUserSwitch(userState, oldUserId, newUserId);
+        continueAndCompleteUserSwitch(userState, oldUserId, newUserId);
         verify(mInjector.getWindowManager(), times(expectedNumberOfCalls))
                 .stopFreezingScreen();
         continueUserSwitchAssertions(newUserId, expectOldUserStopping);
@@ -701,6 +733,7 @@
         private final IStorageManager mStorageManagerMock;
         private final UserManagerInternal mUserManagerInternalMock;
         private final WindowManagerService mWindowManagerMock;
+        private final KeyguardManager mKeyguardManagerMock;
 
         private final Context mCtx;
 
@@ -715,6 +748,8 @@
             mUserManagerInternalMock = mock(UserManagerInternal.class);
             mWindowManagerMock = mock(WindowManagerService.class);
             mStorageManagerMock = mock(IStorageManager.class);
+            mKeyguardManagerMock = mock(KeyguardManager.class);
+            when(mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
         }
 
         @Override
@@ -754,6 +789,11 @@
         }
 
         @Override
+        KeyguardManager getKeyguardManager() {
+            return mKeyguardManagerMock;
+        }
+
+        @Override
         void updateUserConfiguration() {
             Log.i(TAG, "updateUserConfiguration");
         }
@@ -787,6 +827,11 @@
         protected IStorageManager getStorageManager() {
             return mStorageManagerMock;
         }
+
+        @Override
+        protected void dismissKeyguard(Runnable runnable, String reason) {
+            runnable.run();
+        }
     }
 
     private static class TestHandler extends Handler {
diff --git a/services/tests/servicestests/src/com/android/server/backup/transport/DelegatingTransportTest.java b/services/tests/servicestests/src/com/android/server/backup/transport/DelegatingTransportTest.java
deleted file mode 100644
index bae11eb..0000000
--- a/services/tests/servicestests/src/com/android/server/backup/transport/DelegatingTransportTest.java
+++ /dev/null
@@ -1,386 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.backup.transport;
-
-import static junit.framework.Assert.assertEquals;
-
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import android.app.backup.RestoreDescription;
-import android.app.backup.RestoreSet;
-import android.content.Intent;
-import android.content.pm.PackageInfo;
-import android.os.ParcelFileDescriptor;
-import android.os.RemoteException;
-import android.platform.test.annotations.Presubmit;
-
-import androidx.test.runner.AndroidJUnit4;
-
-import com.android.internal.backup.IBackupTransport;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@Presubmit
-@RunWith(AndroidJUnit4.class)
-public class DelegatingTransportTest {
-    @Mock private IBackupTransport mBackupTransport;
-    @Mock private PackageInfo mPackageInfo;
-    @Mock private ParcelFileDescriptor mFd;
-
-    private final String mPackageName = "testpackage";
-    private final RestoreSet mRestoreSet = new RestoreSet();
-    private final int mFlags = 1;
-    private final long mRestoreToken = 10;
-    private final long mSize = 100;
-    private final int mNumBytes = 1000;
-    private DelegatingTransport mDelegatingTransport;
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        mDelegatingTransport = new DelegatingTransport() {
-            @Override
-            protected IBackupTransport getDelegate() {
-                return mBackupTransport;
-            }
-        };
-    }
-
-    @Test
-    public void testName() throws RemoteException {
-        String exp = "dummy";
-        when(mBackupTransport.name()).thenReturn(exp);
-
-        String ret = mDelegatingTransport.name();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).name();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testConfigurationIntent() throws RemoteException {
-        Intent exp = new Intent("dummy");
-        when(mBackupTransport.configurationIntent()).thenReturn(exp);
-
-        Intent ret = mDelegatingTransport.configurationIntent();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).configurationIntent();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testCurrentDestinationString() throws RemoteException {
-        String exp = "dummy";
-        when(mBackupTransport.currentDestinationString()).thenReturn(exp);
-
-        String ret = mDelegatingTransport.currentDestinationString();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).currentDestinationString();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testDataManagementIntent() throws RemoteException {
-        Intent exp = new Intent("dummy");
-        when(mBackupTransport.dataManagementIntent()).thenReturn(exp);
-
-        Intent ret = mDelegatingTransport.dataManagementIntent();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).dataManagementIntent();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testDataManagementIntentLabel() throws RemoteException {
-        String exp = "dummy";
-        when(mBackupTransport.dataManagementIntentLabel()).thenReturn(exp);
-
-        CharSequence ret = mDelegatingTransport.dataManagementIntentLabel();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).dataManagementIntentLabel();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testTransportDirName() throws RemoteException {
-        String exp = "dummy";
-        when(mBackupTransport.transportDirName()).thenReturn(exp);
-
-        String ret = mDelegatingTransport.transportDirName();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).transportDirName();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testRequestBackupTime() throws RemoteException {
-        long exp = 1000L;
-        when(mBackupTransport.requestBackupTime()).thenReturn(exp);
-
-        long ret = mDelegatingTransport.requestBackupTime();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).requestBackupTime();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testInitializeDevice() throws RemoteException {
-        int exp = 1000;
-        when(mBackupTransport.initializeDevice()).thenReturn(exp);
-
-        long ret = mDelegatingTransport.initializeDevice();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).initializeDevice();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testPerformBackup() throws RemoteException {
-        int exp = 1000;
-        when(mBackupTransport.performBackup(mPackageInfo, mFd, mFlags)).thenReturn(exp);
-
-        int ret = mDelegatingTransport.performBackup(mPackageInfo, mFd, mFlags);
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).performBackup(mPackageInfo, mFd, mFlags);
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testClearBackupData() throws RemoteException {
-        int exp = 1000;
-        when(mBackupTransport.clearBackupData(mPackageInfo)).thenReturn(exp);
-
-        int ret = mDelegatingTransport.clearBackupData(mPackageInfo);
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).clearBackupData(mPackageInfo);
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testFinishBackup() throws RemoteException {
-        int exp = 1000;
-        when(mBackupTransport.finishBackup()).thenReturn(exp);
-
-        int ret = mDelegatingTransport.finishBackup();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).finishBackup();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testGetAvailableRestoreSets() throws RemoteException {
-        RestoreSet[] exp = new RestoreSet[] {mRestoreSet};
-        when(mBackupTransport.getAvailableRestoreSets()).thenReturn(exp);
-
-        RestoreSet[] ret = mDelegatingTransport.getAvailableRestoreSets();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).getAvailableRestoreSets();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testGetCurrentRestoreSet() throws RemoteException {
-        long exp = 1000;
-        when(mBackupTransport.getCurrentRestoreSet()).thenReturn(exp);
-
-        long ret = mDelegatingTransport.getCurrentRestoreSet();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).getCurrentRestoreSet();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testStartRestore() throws RemoteException {
-        int exp = 1000;
-        PackageInfo[] packageInfos = {mPackageInfo};
-        when(mBackupTransport.startRestore(mRestoreToken, packageInfos)).thenReturn(exp);
-
-        int ret = mDelegatingTransport.startRestore(mRestoreToken, packageInfos);
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).startRestore(mRestoreToken, packageInfos);
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testNextRestorePackage() throws RemoteException {
-        RestoreDescription exp = new RestoreDescription(mPackageName, 1);
-        when(mBackupTransport.nextRestorePackage()).thenReturn(exp);
-
-        RestoreDescription ret = mDelegatingTransport.nextRestorePackage();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).nextRestorePackage();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testGetRestoreData() throws RemoteException {
-        int exp = 1000;
-        when(mBackupTransport.getRestoreData(mFd)).thenReturn(exp);
-
-        int ret = mDelegatingTransport.getRestoreData(mFd);
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).getRestoreData(mFd);
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void tesFinishRestore() throws RemoteException {
-        mDelegatingTransport.finishRestore();
-
-        verify(mBackupTransport, times(1)).finishRestore();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testRequestFullBackupTime() throws RemoteException {
-        long exp = 1000L;
-        when(mBackupTransport.requestFullBackupTime()).thenReturn(exp);
-
-        long ret = mDelegatingTransport.requestFullBackupTime();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).requestFullBackupTime();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testPerformFullBackup() throws RemoteException {
-        int exp = 1000;
-        when(mBackupTransport.performFullBackup(mPackageInfo, mFd, mFlags)).thenReturn(exp);
-
-        int ret = mDelegatingTransport.performFullBackup(mPackageInfo, mFd, mFlags);
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).performFullBackup(mPackageInfo, mFd, mFlags);
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testCheckFullBackupSize() throws RemoteException {
-        int exp = 1000;
-        when(mBackupTransport.checkFullBackupSize(mSize)).thenReturn(exp);
-
-        int ret = mDelegatingTransport.checkFullBackupSize(mSize);
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).checkFullBackupSize(mSize);
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testSendBackupData() throws RemoteException {
-        int exp = 1000;
-        when(mBackupTransport.sendBackupData(mNumBytes)).thenReturn(exp);
-
-        int ret = mDelegatingTransport.sendBackupData(mNumBytes);
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).sendBackupData(mNumBytes);
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testCancelFullBackup() throws RemoteException {
-        mDelegatingTransport.cancelFullBackup();
-
-        verify(mBackupTransport, times(1)).cancelFullBackup();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testIsAppEligibleForBackup() throws RemoteException {
-        boolean exp = true;
-        when(mBackupTransport.isAppEligibleForBackup(mPackageInfo, true)).thenReturn(exp);
-
-        boolean ret = mDelegatingTransport.isAppEligibleForBackup(mPackageInfo, true);
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).isAppEligibleForBackup(mPackageInfo, true);
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testGetBackupQuota() throws RemoteException {
-        long exp = 1000;
-        when(mBackupTransport.getBackupQuota(mPackageName, true)).thenReturn(exp);
-
-        long ret = mDelegatingTransport.getBackupQuota(mPackageName, true);
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).getBackupQuota(mPackageName, true);
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testGetNextFullRestoreDataChunk() throws RemoteException {
-        int exp = 1000;
-        when(mBackupTransport.getNextFullRestoreDataChunk(mFd)).thenReturn(exp);
-
-        int ret = mDelegatingTransport.getNextFullRestoreDataChunk(mFd);
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).getNextFullRestoreDataChunk(mFd);
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testAbortFullRestore() throws RemoteException {
-        int exp = 1000;
-        when(mBackupTransport.abortFullRestore()).thenReturn(exp);
-
-        int ret = mDelegatingTransport.abortFullRestore();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).abortFullRestore();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-
-    @Test
-    public void testGetTransportFlags() throws RemoteException {
-        int exp = 1000;
-        when(mBackupTransport.getTransportFlags()).thenReturn(exp);
-
-        int ret = mDelegatingTransport.getTransportFlags();
-
-        assertEquals(exp, ret);
-        verify(mBackupTransport, times(1)).getTransportFlags();
-        verifyNoMoreInteractions(mBackupTransport);
-    }
-}
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 e3e3900..d192697 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
@@ -143,8 +143,8 @@
 
         final ClientMonitorCallbackConverter listener1 = mock(ClientMonitorCallbackConverter.class);
 
-        final BiometricPromptClientMonitor client1 =
-                new BiometricPromptClientMonitor(mContext, mToken, lazyDaemon1, listener1);
+        final TestAuthenticationClient client1 =
+                new TestAuthenticationClient(mContext, lazyDaemon1, mToken, listener1);
         final TestClientMonitor client2 = new TestClientMonitor(mContext, mToken, lazyDaemon2);
 
         final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class);
@@ -180,8 +180,8 @@
     @Test
     public void testCancelNotInvoked_whenOperationWaitingForCookie() {
         final HalClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> mock(Object.class);
-        final BiometricPromptClientMonitor client1 = new BiometricPromptClientMonitor(mContext,
-                mToken, lazyDaemon1, mock(ClientMonitorCallbackConverter.class));
+        final TestAuthenticationClient client1 = new TestAuthenticationClient(mContext,
+                lazyDaemon1, mToken, mock(ClientMonitorCallbackConverter.class));
         final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class);
 
         // Schedule a BiometricPrompt authentication request
@@ -195,6 +195,8 @@
         // should go back to idle, since in this case the framework has not even requested the HAL
         // to authenticate yet.
         mScheduler.cancelAuthenticationOrDetection(mToken, 1 /* requestId */);
+        assertTrue(client1.isAlreadyDone());
+        assertTrue(client1.mDestroyed);
         assertNull(mScheduler.mCurrentOperation);
     }
 
@@ -316,6 +318,10 @@
                 eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED),
                 eq(0) /* vendorCode */);
         assertNull(mScheduler.getCurrentClient());
+        assertTrue(client1.isAlreadyDone());
+        assertTrue(client1.mDestroyed);
+        assertTrue(client2.isAlreadyDone());
+        assertTrue(client2.mDestroyed);
     }
 
     @Test
@@ -465,39 +471,9 @@
         return BiometricSchedulerProto.parseFrom(mScheduler.dumpProtoState(clearSchedulerBuffer));
     }
 
-    private static class BiometricPromptClientMonitor extends AuthenticationClient<Object> {
-
-        public BiometricPromptClientMonitor(@NonNull Context context, @NonNull IBinder token,
-                @NonNull LazyDaemon<Object> lazyDaemon, ClientMonitorCallbackConverter listener) {
-            super(context, lazyDaemon, token, listener, 0 /* targetUserId */, 0 /* operationId */,
-                    false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */,
-                    TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */,
-                    0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class),
-                    false /* isKeyguard */, true /* shouldVibrate */,
-                    false /* isKeyguardBypassEnabled */);
-        }
-
-        @Override
-        protected void stopHalOperation() {
-        }
-
-        @Override
-        protected void startHalOperation() {
-        }
-
-        @Override
-        protected void handleLifecycleAfterAuth(boolean authenticated) {
-
-        }
-
-        @Override
-        public boolean wasUserDetected() {
-            return false;
-        }
-    }
-
     private static class TestAuthenticationClient extends AuthenticationClient<Object> {
         int mNumCancels = 0;
+        boolean mDestroyed = false;
 
         public TestAuthenticationClient(@NonNull Context context,
                 @NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token,
@@ -530,6 +506,13 @@
             return false;
         }
 
+        @Override
+        public void destroy() {
+            mDestroyed = true;
+            super.destroy();
+        }
+
+        @Override
         public void cancel() {
             mNumCancels++;
             super.cancel();
@@ -595,6 +578,7 @@
 
         @Override
         public void destroy() {
+            super.destroy();
             mDestroyed = true;
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index 0248b9b..d926dcb 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -265,9 +265,10 @@
     }
 
     @Test
-    public void testInstallerCanSetOverrides() throws Exception {
+    public void testInstallerCanAddOverrides() throws Exception {
         final long disabledChangeId1 = 1234L;
         final long disabledChangeId2 = 1235L;
+        final long unknownChangeId = 1236L;
         // We make disabledChangeId2 non-overridable to make sure it is ignored.
         CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
                 .addDisabledOverridableChangeWithId(disabledChangeId1)
@@ -284,19 +285,25 @@
         // Force the validator to prevent overriding non-overridable changes by using a user build.
         when(mBuildClassifier.isDebuggableBuild()).thenReturn(false);
         when(mBuildClassifier.isFinalBuild()).thenReturn(true);
+        Map<Long, PackageOverride> overrides = new HashMap<>();
+        overrides.put(disabledChangeId1, new PackageOverride.Builder()
+                .setMaxVersionCode(99L)
+                .setEnabled(true)
+                .build());
+        // Adding an unknown change ID to make sure it's skipped if skipUnknownChangeIds is true.
+        overrides.put(unknownChangeId, new PackageOverride.Builder().setEnabled(false).build());
+        CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
 
-        CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(
-                Collections.singletonMap(disabledChangeId1,
-                        new PackageOverride.Builder()
-                                .setMaxVersionCode(99L)
-                                .setEnabled(true)
-                                .build()));
-
-        compatConfig.addOverrides(config, "com.some.package");
+        compatConfig.addPackageOverrides(config, "com.some.package", /* skipUnknownChangeIds */
+                true);
         assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
         assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse();
+        // Making sure the unknown change ID is still unknown and isChangeEnabled returns true.
+        assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isFalse();
+        assertThat(compatConfig.isChangeEnabled(unknownChangeId, applicationInfo)).isTrue();
     }
 
+
     @Test
     public void testPreventInstallerSetNonOverridable() throws Exception {
         final long disabledChangeId1 = 1234L;
@@ -326,7 +333,8 @@
         CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
 
         assertThrows(SecurityException.class,
-                () -> compatConfig.addOverrides(config, "com.some.package")
+                () -> compatConfig.addPackageOverrides(config, "com.some.package",
+                        /* skipUnknownChangeIds */ true)
         );
         assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isTrue();
         assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isFalse();
@@ -334,6 +342,38 @@
     }
 
     @Test
+    public void testCanAddOverridesForUnknownChangeIdOnDebugBuild() throws Exception {
+        final long disabledChangeId = 1234L;
+        final long unknownChangeId = 1235L;
+        // We make disabledChangeId2 non-overridable to make sure it is ignored.
+        CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
+                .addDisabledChangeWithId(disabledChangeId)
+                .build();
+        ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
+                .withPackageName("com.some.package")
+                .build();
+        PackageManager packageManager = mock(PackageManager.class);
+        when(mContext.getPackageManager()).thenReturn(packageManager);
+        when(packageManager.getApplicationInfo(eq("com.some.package"), anyInt()))
+                .thenReturn(applicationInfo);
+
+        when(mBuildClassifier.isDebuggableBuild()).thenReturn(true);
+        Map<Long, PackageOverride> overrides = new HashMap<>();
+        overrides.put(disabledChangeId, new PackageOverride.Builder().setEnabled(true).build());
+        // Adding an unknown change ID to make sure it isn't skipped if skipUnknownChangeIds is
+        // false.
+        overrides.put(unknownChangeId, new PackageOverride.Builder().setEnabled(false).build());
+        CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
+
+        compatConfig.addPackageOverrides(config, "com.some.package", /* skipUnknownChangeIds */
+                false);
+        assertThat(compatConfig.isChangeEnabled(disabledChangeId, applicationInfo)).isTrue();
+        // Making sure the unknown change ID is now known and has an override.
+        assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isTrue();
+        assertThat(compatConfig.isChangeEnabled(unknownChangeId, applicationInfo)).isFalse();
+    }
+
+    @Test
     public void testApplyDeferredOverridesAfterInstallingApp() throws Exception {
         ApplicationInfo applicationInfo = ApplicationInfoBuilder.create()
                 .withPackageName("com.notinstalled.foo")
@@ -377,7 +417,8 @@
                                 .setMaxVersionCode(99L)
                                 .setEnabled(true)
                                 .build()));
-        compatConfig.addOverrides(config, "com.installed.foo");
+        compatConfig.addPackageOverrides(config, "com.installed.foo", /* skipUnknownChangeIds */
+                true);
         assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
 
         // Add override that does include the installed app version
@@ -388,7 +429,8 @@
                                 .setMaxVersionCode(100L)
                                 .setEnabled(true)
                                 .build()));
-        compatConfig.addOverrides(config, "com.installed.foo");
+        compatConfig.addPackageOverrides(config, "com.installed.foo", /* skipUnknownChangeIds */
+                true);
         assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isTrue();
     }
 
@@ -411,7 +453,8 @@
                         .setMaxVersionCode(99L)
                         .setEnabled(true)
                         .build()));
-        compatConfig.addOverrides(config, "com.notinstalled.foo");
+        compatConfig.addPackageOverrides(config, "com.notinstalled.foo", /* skipUnknownChangeIds */
+                true);
         assertThat(compatConfig.isChangeEnabled(1234L, applicationInfo)).isFalse();
 
         // Pretend the app is now installed.
@@ -557,6 +600,7 @@
         final long disabledChangeId1 = 1234L;
         final long disabledChangeId2 = 1235L;
         final long enabledChangeId = 1236L;
+        final long unknownChangeId = 1237L;
         // We make disabledChangeId2 non-overridable to make sure it is ignored.
         CompatConfig compatConfig = CompatConfigBuilder.create(mBuildClassifier, mContext)
                 .addDisabledOverridableChangeWithId(disabledChangeId1)
@@ -583,6 +627,8 @@
         Set<Long> overridesToRemove = new HashSet<>();
         overridesToRemove.add(disabledChangeId1);
         overridesToRemove.add(enabledChangeId);
+        // Adding an unknown change ID to make sure it's skipped.
+        overridesToRemove.add(unknownChangeId);
         CompatibilityOverridesToRemoveConfig config = new CompatibilityOverridesToRemoveConfig(
                 overridesToRemove);
 
@@ -590,6 +636,8 @@
         assertThat(compatConfig.isChangeEnabled(disabledChangeId1, applicationInfo)).isFalse();
         assertThat(compatConfig.isChangeEnabled(disabledChangeId2, applicationInfo)).isTrue();
         assertThat(compatConfig.isChangeEnabled(enabledChangeId, applicationInfo)).isTrue();
+        // Making sure the unknown change ID is still unknown.
+        assertThat(compatConfig.isKnownChangeId(unknownChangeId)).isFalse();
     }
 
     @Test
@@ -797,18 +845,18 @@
                         .build());
         when(mPackageManager.getApplicationInfo(eq("bar.baz"), anyInt()))
                 .thenThrow(new NameNotFoundException());
-        compatConfig.addOverrides(
+        compatConfig.addPackageOverrides(
                 new CompatibilityOverrideConfig(
                         Collections.singletonMap(
                                 1L,
                                 new PackageOverride.Builder().setEnabled(true).build())),
-                "foo.bar");
-        compatConfig.addOverrides(
+                "foo.bar", /* skipUnknownChangeIds */ true);
+        compatConfig.addPackageOverrides(
                 new CompatibilityOverrideConfig(
                         Collections.singletonMap(
                                 2L,
                                 new PackageOverride.Builder().setEnabled(false).build())),
-                "bar.baz");
+                "bar.baz", /* skipUnknownChangeIds */ true);
 
         assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
                 + "<overrides>\n"
@@ -847,12 +895,12 @@
         compatConfig.forceNonDebuggableFinalForTest(true);
         compatConfig.initOverrides(overridesFile, new File(""));
 
-        compatConfig.addOverrides(new CompatibilityOverrideConfig(Collections.singletonMap(1L,
-                new PackageOverride.Builder()
+        compatConfig.addPackageOverrides(new CompatibilityOverrideConfig(
+                Collections.singletonMap(1L, new PackageOverride.Builder()
                         .setMinVersionCode(99L)
                         .setMaxVersionCode(101L)
                         .setEnabled(true)
-                        .build())), "foo.bar");
+                        .build())), "foo.bar", /* skipUnknownChangeIds */ true);
 
         assertThat(readFile(overridesFile)).isEqualTo("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
                 + "<overrides>\n"
diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
index bf621b1..f664517 100644
--- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java
@@ -56,12 +56,9 @@
     private static final int DARKENING_LIGHT_DEBOUNCE_CONFIG = 0;
     private static final float DOZE_SCALE_FACTOR = 0.0f;
     private static final boolean RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG = false;
-    private static final int DISPLAY_ID = 0;
-    private static final int LAYER_STACK = 0;
     private static final int LIGHT_SENSOR_WARMUP_TIME = 0;
 
     private Context mContext;
-    private LogicalDisplay mLogicalDisplay;
     private AutomaticBrightnessController mController;
 
     @Mock SensorManager mSensorManager;
@@ -69,7 +66,6 @@
     @Mock HysteresisLevels mAmbientBrightnessThresholds;
     @Mock HysteresisLevels mScreenBrightnessThresholds;
     @Mock Handler mNoOpHandler;
-    @Mock DisplayDevice mDisplayDevice;
     @Mock HighBrightnessModeController mHbmController;
 
     @Before
@@ -79,7 +75,6 @@
         MockitoAnnotations.initMocks(this);
 
         mContext = InstrumentationRegistry.getContext();
-        mLogicalDisplay = new LogicalDisplay(DISPLAY_ID, LAYER_STACK, mDisplayDevice);
     }
 
     @After
@@ -104,7 +99,7 @@
                 BRIGHTNESS_MAX_FLOAT, DOZE_SCALE_FACTOR, LIGHT_SENSOR_RATE,
                 INITIAL_LIGHT_SENSOR_RATE, BRIGHTENING_LIGHT_DEBOUNCE_CONFIG,
                 DARKENING_LIGHT_DEBOUNCE_CONFIG, RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG,
-                mAmbientBrightnessThresholds, mScreenBrightnessThresholds, mLogicalDisplay,
+                mAmbientBrightnessThresholds, mScreenBrightnessThresholds,
                 mContext, mHbmController
         );
 
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
index 285806b..c675726 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessMappingStrategyTest.java
@@ -59,6 +59,20 @@
         5000
     };
 
+    private static final int[] LUX_LEVELS_IDLE = {
+        0,
+        10,
+        40,
+        80,
+        200,
+        655,
+        1200,
+        2500,
+        4400,
+        8000,
+        10000
+    };
+
     private static final float[] DISPLAY_LEVELS_NITS = {
         13.25f,
         54.0f,
@@ -73,6 +87,20 @@
         478.5f,
     };
 
+    private static final float[] DISPLAY_LEVELS_NITS_IDLE = {
+        23.25f,
+        64.0f,
+        88.85f,
+        115.02f,
+        142.7f,
+        180.12f,
+        222.1f,
+        275.2f,
+        345.8f,
+        425.2f,
+        468.5f,
+    };
+
     private static final int[] DISPLAY_LEVELS_BACKLIGHT = {
         9,
         30,
@@ -88,7 +116,6 @@
     };
 
     private static final float[] DISPLAY_RANGE_NITS = { 2.685f, 478.5f };
-    private static final float[] DISPLAY_LEVELS_RANGE_NITS = { 13.25f, 478.5f };
     private static final float[] BACKLIGHT_RANGE_ZERO_TO_ONE = { 0.0f, 1.0f };
     private static final float[] DISPLAY_LEVELS_RANGE_BACKLIGHT_FLOAT = { 0.03149606299f, 1.0f };
 
@@ -118,6 +145,8 @@
             new float[] { 0.0f, 100.0f, 1000.0f, 2500.0f, 4000.0f, 4900.0f, 5000.0f },
             new float[] { 0.0475f, 0.0475f, 0.2225f, 0.5140f, 0.8056f, 0.9805f, 1.0f });
 
+    private static final float TOLERANCE = 0.0001f;
+
     @Test
     public void testSimpleStrategyMappingAtControlPoints() {
         Resources res = createResources(LUX_LEVELS, DISPLAY_LEVELS_BACKLIGHT);
@@ -357,6 +386,27 @@
         assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy.create(res, ddc));
     }
 
+    @Test
+    public void testIdleModeConfigLoadsCorrectly() {
+        Resources res = createResourcesIdle(LUX_LEVELS_IDLE, DISPLAY_LEVELS_NITS_IDLE);
+        DisplayDeviceConfig ddc = createDdc(DISPLAY_RANGE_NITS, BACKLIGHT_RANGE_ZERO_TO_ONE);
+
+        // Create an idle mode bms
+        // This will fail if it tries to fetch the wrong configuration.
+        BrightnessMappingStrategy bms = BrightnessMappingStrategy.createForIdleMode(res, ddc);
+        assertNotNull("BrightnessMappingStrategy should not be null", bms);
+
+        // Ensure that the config is the one we set
+        // Ensure that the lux -> brightness -> nits path works. ()
+        for (int i = 0; i < DISPLAY_LEVELS_NITS_IDLE.length; i++) {
+            assertEquals(LUX_LEVELS_IDLE[i], bms.getDefaultConfig().getCurve().first[i], TOLERANCE);
+            assertEquals(DISPLAY_LEVELS_NITS_IDLE[i], bms.getDefaultConfig().getCurve().second[i],
+                    TOLERANCE);
+            assertEquals(bms.convertToNits(bms.getBrightness(LUX_LEVELS_IDLE[i])),
+                    DISPLAY_LEVELS_NITS_IDLE[i], TOLERANCE);
+        }
+    }
+
     private static void assertStrategyAdaptsToUserDataPoints(BrightnessMappingStrategy strategy) {
         // Save out all of the initial brightness data for comparison after reset.
         float[] initialBrightnessLevels = new float[LUX_LEVELS.length];
@@ -421,14 +471,39 @@
                 brightnessLevelsNits);
     }
 
+    private Resources createResourcesIdle(int[] luxLevels, float[] brightnessLevelsNits) {
+        return createResources(EMPTY_INT_ARRAY, EMPTY_INT_ARRAY, EMPTY_FLOAT_ARRAY,
+                luxLevels, brightnessLevelsNits);
+    }
+
     private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight,
             float[] brightnessLevelsNits) {
+        return createResources(luxLevels, brightnessLevelsBacklight, brightnessLevelsNits,
+                EMPTY_INT_ARRAY, EMPTY_FLOAT_ARRAY);
+
+    }
+
+    private Resources createResources(int[] luxLevels, int[] brightnessLevelsBacklight,
+            float[] brightnessLevelsNits, int[] luxLevelsIdle, float[] brightnessLevelsNitsIdle) {
+
         Resources mockResources = mock(Resources.class);
+
         // For historical reasons, the lux levels resource implicitly defines the first point as 0,
         // so we need to chop it off of the array the mock resource object returns.
-        int[] luxLevelsResource = Arrays.copyOfRange(luxLevels, 1, luxLevels.length);
-        when(mockResources.getIntArray(com.android.internal.R.array.config_autoBrightnessLevels))
-                .thenReturn(luxLevelsResource);
+        // Don't mock if these values are not set. If we try to use them, we will fail.
+        if (luxLevels.length > 0) {
+            int[] luxLevelsResource = Arrays.copyOfRange(luxLevels, 1, luxLevels.length);
+            when(mockResources.getIntArray(
+                    com.android.internal.R.array.config_autoBrightnessLevels))
+                    .thenReturn(luxLevelsResource);
+        }
+        if (luxLevelsIdle.length > 0) {
+            int[] luxLevelsIdleResource = Arrays.copyOfRange(luxLevelsIdle, 1,
+                    luxLevelsIdle.length);
+            when(mockResources.getIntArray(
+                    com.android.internal.R.array.config_autoBrightnessLevelsIdle))
+                    .thenReturn(luxLevelsIdleResource);
+        }
 
         when(mockResources.getIntArray(
                 com.android.internal.R.array.config_autoBrightnessLcdBacklightValues))
@@ -438,6 +513,10 @@
         when(mockResources.obtainTypedArray(
                 com.android.internal.R.array.config_autoBrightnessDisplayValuesNits))
                 .thenReturn(mockBrightnessLevelNits);
+        TypedArray mockBrightnessLevelNitsIdle = createFloatTypedArray(brightnessLevelsNitsIdle);
+        when(mockResources.obtainTypedArray(
+                com.android.internal.R.array.config_autoBrightnessDisplayValuesNitsIdle))
+                .thenReturn(mockBrightnessLevelNitsIdle);
 
         when(mockResources.getInteger(
                 com.android.internal.R.integer.config_screenBrightnessSettingMinimum))
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
index fbc1952..fefc425 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayMapperTest.java
@@ -38,7 +38,10 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Handler;
+import android.os.IPowerManager;
+import android.os.IThermalService;
 import android.os.Parcel;
+import android.os.PowerManager;
 import android.os.Process;
 import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
@@ -72,10 +75,13 @@
     private LogicalDisplayMapper mLogicalDisplayMapper;
     private TestLooper mLooper;
     private Handler mHandler;
+    private PowerManager mPowerManager;
 
     @Mock LogicalDisplayMapper.Listener mListenerMock;
     @Mock Context mContextMock;
     @Mock Resources mResourcesMock;
+    @Mock IPowerManager mIPowerManagerMock;
+    @Mock IThermalService mIThermalServiceMock;
 
     @Captor ArgumentCaptor<LogicalDisplay> mDisplayCaptor;
 
@@ -105,6 +111,11 @@
         // Disable binder caches in this process.
         PropertyInvalidatedCache.disableForTestMode();
 
+        mPowerManager = new PowerManager(mContextMock, mIPowerManagerMock, mIThermalServiceMock,
+                null);
+        when(mContextMock.getSystemServiceName(PowerManager.class))
+                .thenReturn(Context.POWER_SERVICE);
+        when(mContextMock.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
         when(mContextMock.getResources()).thenReturn(mResourcesMock);
         when(mResourcesMock.getBoolean(
                 com.android.internal.R.bool.config_supportsConcurrentInternalDisplays))
@@ -301,7 +312,6 @@
                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
     }
 
-
     /////////////////
     // Helper Methods
     /////////////////
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
index cf4bdf6..b588db6 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ActiveSourceActionTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.hdmi;
 
+import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 import static com.android.server.hdmi.Constants.ADDR_TV;
 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
 
@@ -153,6 +154,7 @@
                 mHdmiControlService);
         audioDevice.init();
         mLocalDevices.add(audioDevice);
+        mHdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
         mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
         mTestLooper.dispatchAll();
 
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
index 4ff7c669..ff01cb1 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcInitiationActionFromAvrTest.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.hdmi;
 
+import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -115,6 +116,7 @@
         mAction = new ArcInitiationActionFromAvr(mHdmiCecLocalDeviceAudioSystem);
 
         mLocalDevices.add(mHdmiCecLocalDeviceAudioSystem);
+        hdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
         hdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
         mTestLooper.dispatchAll();
     }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
index c6bb914..a44a5cd 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/ArcTerminationActionFromAvrTest.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.hdmi;
 
+import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 import static com.android.server.hdmi.HdmiControlService.INITIATED_BY_ENABLE_CEC;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -114,6 +115,7 @@
         mAction = new ArcTerminationActionFromAvr(mHdmiCecLocalDeviceAudioSystem);
 
         mLocalDevices.add(mHdmiCecLocalDeviceAudioSystem);
+        hdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
         hdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
         mHdmiCecLocalDeviceAudioSystem.setArcStatus(true);
         mTestLooper.dispatchAll();
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakePowerManagerInternalWrapper.java b/services/tests/servicestests/src/com/android/server/hdmi/FakePowerManagerInternalWrapper.java
new file mode 100644
index 0000000..968a75c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/hdmi/FakePowerManagerInternalWrapper.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 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.hdmi;
+
+/**
+ * Fake class which stubs PowerManagerInternalWrapper (useful for testing).
+ */
+public class FakePowerManagerInternalWrapper extends PowerManagerInternalWrapper {
+
+    private long mIdleDurationMs = -1;
+
+    /**
+     * Sets the duration (in milliseconds) that this device has been idle for.
+     */
+    public void setIdleDuration(long idleDurationMs) {
+        mIdleDurationMs = idleDurationMs;
+    }
+
+    @Override
+    public boolean wasDeviceIdleFor(long ms) {
+        return ms <= mIdleDurationMs;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index 17f827d..a411392 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.hdmi;
 
+import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 import static com.android.server.hdmi.Constants.ADDR_AUDIO_SYSTEM;
 import static com.android.server.hdmi.Constants.ADDR_BROADCAST;
 import static com.android.server.hdmi.Constants.ADDR_PLAYBACK_1;
@@ -206,6 +207,7 @@
                 4, HdmiPortInfo.PORT_INPUT, HDMI_3_PHYSICAL_ADDRESS, true, false, false);
         mNativeWrapper.setPortInfo(mHdmiPortInfo);
         mHdmiControlService.initService();
+        mHdmiControlService.onBootPhase(PHASE_SYSTEM_SERVICES_READY);
         mPowerManager = new FakePowerManagerWrapper(context);
         mHdmiControlService.setPowerManager(mPowerManager);
         // No TV device interacts with AVR so system audio control won't be turned on here
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index 055459c..2d13e69 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -76,6 +76,8 @@
     private int mPlaybackLogicalAddress;
     private boolean mWokenUp;
     private boolean mActiveMediaSessionsPaused;
+    private FakePowerManagerInternalWrapper mPowerManagerInternal =
+            new FakePowerManagerInternalWrapper();
 
     @Before
     public void setUp() {
@@ -146,6 +148,7 @@
         mHdmiControlService.initService();
         mPowerManager = new FakePowerManagerWrapper(context);
         mHdmiControlService.setPowerManager(mPowerManager);
+        mHdmiControlService.setPowerManagerInternal(mPowerManagerInternal);
         mHdmiControlService.allocateLogicalAddress(mLocalDevices, INITIATED_BY_ENABLE_CEC);
         mPlaybackPhysicalAddress = 0x2000;
         mNativeWrapper.setPhysicalAddress(mPlaybackPhysicalAddress);
@@ -1969,4 +1972,41 @@
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortPressed);
         assertThat(mNativeWrapper.getResultMessages()).doesNotContain(featureAbortReleased);
     }
+
+    @Test
+    public void onHotplugInAfterHotplugOut_noStandbyAfterDelay() {
+        mPowerManager.setInteractive(true);
+        mNativeWrapper.onHotplugEvent(1, false);
+        mTestLooper.dispatchAll();
+
+        mTestLooper.moveTimeForward(
+                HdmiCecLocalDevicePlayback.STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS / 2);
+        mNativeWrapper.onHotplugEvent(1, true);
+        mTestLooper.dispatchAll();
+
+        mPowerManagerInternal.setIdleDuration(
+                HdmiCecLocalDevicePlayback.STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS);
+        mTestLooper.moveTimeForward(HdmiCecLocalDevicePlayback.STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS);
+        mTestLooper.dispatchAll();
+
+        assertThat(mPowerManager.isInteractive()).isTrue();
+    }
+
+    @Test
+    public void onHotplugOut_standbyAfterDelay_onlyAfterDeviceIdle() {
+        mPowerManager.setInteractive(true);
+        mNativeWrapper.onHotplugEvent(1, false);
+        mTestLooper.dispatchAll();
+
+        mPowerManagerInternal.setIdleDuration(0);
+        mTestLooper.moveTimeForward(HdmiCecLocalDevicePlayback.STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS);
+        mTestLooper.dispatchAll();
+        assertThat(mPowerManager.isInteractive()).isTrue();
+
+        mPowerManagerInternal.setIdleDuration(
+                HdmiCecLocalDevicePlayback.STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS);
+        mTestLooper.moveTimeForward(HdmiCecLocalDevicePlayback.STANDBY_AFTER_HOTPLUG_OUT_DELAY_MS);
+        mTestLooper.dispatchAll();
+        assertThat(mPowerManager.isInteractive()).isFalse();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/health/HealthServiceWrapperTest.java b/services/tests/servicestests/src/com/android/server/health/HealthServiceWrapperTest.java
index c97a67b..16d97a4 100644
--- a/services/tests/servicestests/src/com/android/server/health/HealthServiceWrapperTest.java
+++ b/services/tests/servicestests/src/com/android/server/health/HealthServiceWrapperTest.java
@@ -19,11 +19,12 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.fail;
 
+import static org.mockito.AdditionalMatchers.not;
 import static org.mockito.Mockito.*;
 
-import android.hardware.health.V2_0.IHealth;
 import android.hidl.manager.V1_0.IServiceManager;
 import android.hidl.manager.V1_0.IServiceNotification;
+import android.os.IServiceCallback;
 import android.os.RemoteException;
 
 import androidx.test.filters.SmallTest;
@@ -44,28 +45,47 @@
 
 @RunWith(AndroidJUnit4.class)
 public class HealthServiceWrapperTest {
-
     @Mock IServiceManager mMockedManager;
-    @Mock IHealth mMockedHal;
-    @Mock IHealth mMockedHal2;
+    @Mock android.hardware.health.V2_0.IHealth mMockedHal;
+    @Mock android.hardware.health.V2_0.IHealth mMockedHal2;
 
     @Mock HealthServiceWrapperHidl.Callback mCallback;
     @Mock HealthServiceWrapperHidl.IServiceManagerSupplier mManagerSupplier;
     @Mock HealthServiceWrapperHidl.IHealthSupplier mHealthServiceSupplier;
+
+    @Mock android.hardware.health.IHealth.Stub mMockedAidlHal;
+    @Mock android.hardware.health.IHealth.Stub mMockedAidlHal2;
+    @Mock HealthServiceWrapperAidl.ServiceManagerStub mMockedAidlManager;
+    @Mock HealthRegCallbackAidl mRegCallbackAidl;
+
     HealthServiceWrapper mWrapper;
 
     private static final String VENDOR = HealthServiceWrapperHidl.INSTANCE_VENDOR;
+    private static final String AIDL_SERVICE_NAME = HealthServiceWrapperAidl.SERVICE_NAME;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+
+        // Mocks the conversion between IHealth and IBinder.
+        when(mMockedAidlHal.asBinder()).thenCallRealMethod(); // returns mMockedAidlHal
+        when(mMockedAidlHal2.asBinder()).thenCallRealMethod(); // returns mMockedAidlHal2
+        when(mMockedAidlHal.queryLocalInterface(android.hardware.health.IHealth.DESCRIPTOR))
+                .thenReturn(mMockedAidlHal);
+        when(mMockedAidlHal2.queryLocalInterface(android.hardware.health.IHealth.DESCRIPTOR))
+                .thenReturn(mMockedAidlHal2);
     }
 
     @After
     public void tearDown() {
+        validateMockitoUsage();
         if (mWrapper != null) mWrapper.getHandlerThread().quitSafely();
     }
 
+    public static <T> ArgumentMatcher<T> isOneOf(T[] collection) {
+        return isOneOf(Arrays.asList(collection));
+    }
+
     public static <T> ArgumentMatcher<T> isOneOf(Collection<T> collection) {
         return new ArgumentMatcher<T>() {
             @Override
@@ -75,13 +95,39 @@
 
             @Override
             public String toString() {
-                return collection.toString();
+                return "is one of " + collection.toString();
             }
         };
     }
 
-    private void initForInstances(String... instanceNamesArr) throws Exception {
-        final Collection<String> instanceNames = Arrays.asList(instanceNamesArr);
+    /**
+     * Set up mock objects to pretend that the given AIDL and HIDL instances exists.
+     *
+     * <p>Also, when registering service notifications, the mocked service managers immediately
+     * sends 3 registration notifications, including 2 referring to the original HAL and 1 referring
+     * to the new HAL.
+     *
+     * @param aidlInstances e.g. {"android.hardware.health.IHealth/default"}
+     * @param hidlInstances e.g. {"default", "backup"}
+     * @throws Exception
+     */
+    private void initForInstances(String[] aidlInstances, String[] hidlInstances) throws Exception {
+        doAnswer(
+                (invocation) -> {
+                    sendAidlRegCallback(invocation, mMockedAidlHal);
+                    sendAidlRegCallback(invocation, mMockedAidlHal);
+                    sendAidlRegCallback(invocation, mMockedAidlHal2);
+                    return null;
+                })
+                .when(mMockedAidlManager)
+                .registerForNotifications(
+                        argThat(isOneOf(aidlInstances)), any(IServiceCallback.class));
+        when(mMockedAidlManager.waitForDeclaredService(argThat(isOneOf(aidlInstances))))
+                .thenReturn(mMockedAidlHal)
+                .thenThrow(new RuntimeException("waitForDeclaredService called more than once"));
+        when(mMockedAidlManager.waitForDeclaredService(not(argThat(isOneOf(aidlInstances)))))
+                .thenReturn(null);
+
         doAnswer(
                 (invocation) -> {
                     // technically, preexisting is ignored by
@@ -93,8 +139,8 @@
                 })
                 .when(mMockedManager)
                 .registerForNotifications(
-                        eq(IHealth.kInterfaceName),
-                        argThat(isOneOf(instanceNames)),
+                        eq(android.hardware.health.V2_0.IHealth.kInterfaceName),
+                        argThat(isOneOf(hidlInstances)),
                         any(IServiceNotification.class));
 
         doReturn(mMockedManager).when(mManagerSupplier).get();
@@ -104,7 +150,7 @@
                 .doReturn(mMockedHal2) // notification 3
                 .doThrow(new RuntimeException("Should not call getService for more than 4 times"))
                 .when(mHealthServiceSupplier)
-                .get(argThat(isOneOf(instanceNames)));
+                .get(argThat(isOneOf(hidlInstances)));
     }
 
     private void waitHandlerThreadFinish() throws Exception {
@@ -121,19 +167,62 @@
             throws Exception {
         ((IServiceNotification) invocation.getArguments()[2])
                 .onRegistration(
-                        IHealth.kInterfaceName, (String) invocation.getArguments()[1], preexisting);
+                        android.hardware.health.V2_0.IHealth.kInterfaceName,
+                        (String) invocation.getArguments()[1],
+                        preexisting);
+    }
+
+    private static void sendAidlRegCallback(
+            InvocationOnMock invocation, android.hardware.health.IHealth service) throws Exception {
+        ((IServiceCallback) invocation.getArguments()[1])
+                .onRegistration((String) invocation.getArguments()[0], service.asBinder());
     }
 
     private void createWrapper() throws RemoteException {
-        mWrapper = HealthServiceWrapper.create(mCallback, mManagerSupplier, mHealthServiceSupplier);
+        mWrapper =
+                HealthServiceWrapper.create(
+                        mRegCallbackAidl,
+                        mMockedAidlManager,
+                        mCallback,
+                        mManagerSupplier,
+                        mHealthServiceSupplier);
     }
 
     @SmallTest
     @Test
-    public void testWrapPreferVendor() throws Exception {
-        initForInstances(VENDOR);
+    public void testWrapAidlOnly() throws Exception {
+        initForInstances(new String[] {AIDL_SERVICE_NAME}, new String[0]);
         createWrapper();
         waitHandlerThreadFinish();
+        verify(mRegCallbackAidl, times(1)).onRegistration(same(null), same(mMockedAidlHal));
+        verify(mRegCallbackAidl, never())
+                .onRegistration(same(mMockedAidlHal), same(mMockedAidlHal));
+        verify(mRegCallbackAidl, times(1))
+                .onRegistration(same(mMockedAidlHal), same(mMockedAidlHal2));
+        verify(mCallback, never()).onRegistration(any(), any(), anyString());
+    }
+
+    @SmallTest
+    @Test
+    public void testWrapPreferAidl() throws Exception {
+        initForInstances(new String[] {AIDL_SERVICE_NAME}, new String[] {VENDOR});
+        createWrapper();
+        waitHandlerThreadFinish();
+        verify(mRegCallbackAidl, times(1)).onRegistration(same(null), same(mMockedAidlHal));
+        verify(mRegCallbackAidl, never())
+                .onRegistration(same(mMockedAidlHal), same(mMockedAidlHal));
+        verify(mRegCallbackAidl, times(1))
+                .onRegistration(same(mMockedAidlHal), same(mMockedAidlHal2));
+        verify(mCallback, never()).onRegistration(any(), any(), anyString());
+    }
+
+    @SmallTest
+    @Test
+    public void testWrapFallbackHidl() throws Exception {
+        initForInstances(new String[0], new String[] {VENDOR});
+        createWrapper();
+        waitHandlerThreadFinish();
+        verify(mRegCallbackAidl, never()).onRegistration(any(), any());
         verify(mCallback, times(1)).onRegistration(same(null), same(mMockedHal), eq(VENDOR));
         verify(mCallback, never()).onRegistration(same(mMockedHal), same(mMockedHal), anyString());
         verify(mCallback, times(1)).onRegistration(same(mMockedHal), same(mMockedHal2), eq(VENDOR));
@@ -142,7 +231,7 @@
     @SmallTest
     @Test
     public void testNoService() throws Exception {
-        initForInstances("unrelated");
+        initForInstances(new String[0], new String[] {"unrelated"});
         try {
             createWrapper();
             fail("Expect NoSuchElementException");
diff --git a/services/tests/servicestests/src/com/android/server/pm/BundleUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/BundleUtilsTest.java
index 764c504..6245f82 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BundleUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BundleUtilsTest.java
@@ -22,8 +22,9 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import android.os.Bundle;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.BundleUtils;
@@ -35,6 +36,7 @@
  * Build/Install/Run:
  * atest com.android.server.pm.BundleUtilsTest
  */
+@Presubmit
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class BundleUtilsTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java b/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java
index b228c83..54ab133 100644
--- a/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/CompatibilityModeTest.java
@@ -32,6 +32,7 @@
 import android.content.pm.parsing.PackageInfoWithoutStateUtils;
 import android.content.pm.parsing.ParsingPackageUtils;
 import android.os.Build;
+import android.platform.test.annotations.Presubmit;
 
 import com.android.server.pm.parsing.pkg.PackageImpl;
 import com.android.server.pm.pkg.PackageUserStateImpl;
@@ -40,6 +41,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
+@Presubmit
 public class CompatibilityModeTest {
 
     private boolean mCompatibilityModeEnabled;;
diff --git a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
index 9631863..6b6d84a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
@@ -20,6 +20,7 @@
 import static android.content.pm.parsing.ParsingPackageUtils.parsePublicKey;
 
 import android.content.pm.Signature;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -33,6 +34,7 @@
 import java.security.PublicKey;
 import java.security.cert.CertificateException;
 
+@Presubmit
 public class KeySetManagerServiceTest extends AndroidTestCase {
 
     private WatchedArrayMap<String, PackageSetting> mPackagesMap;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java b/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
index 6a9ef8a..9ea7907 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ModuleInfoProviderTest.java
@@ -21,6 +21,7 @@
 import android.content.Context;
 import android.content.pm.ModuleInfo;
 import android.content.pm.PackageManager;
+import android.platform.test.annotations.Presubmit;
 import android.test.InstrumentationTestCase;
 
 import com.android.frameworks.servicestests.R;
@@ -30,6 +31,7 @@
 import java.util.Collections;
 import java.util.List;
 
+@Presubmit
 public class ModuleInfoProviderTest extends InstrumentationTestCase {
 
     @Mock private ApexManager mApexManager;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index 734fdba..b81a4ef 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.pm;
 
+import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
+
 import static com.google.common.truth.Truth.assertWithMessage;
 
 import static org.junit.Assert.fail;
@@ -27,11 +29,18 @@
 import static java.lang.reflect.Modifier.isStatic;
 
 import android.annotation.Nullable;
+import android.app.AppGlobals;
 import android.content.IIntentReceiver;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.os.Bundle;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
 import android.util.SparseArray;
 
+import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.HexDump;
@@ -42,6 +51,7 @@
 
 import org.junit.After;
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -60,10 +70,21 @@
 // atest PackageManagerServiceTest
 // runtest -c com.android.server.pm.PackageManagerServiceTest frameworks-services
 // bit FrameworksServicesTests:com.android.server.pm.PackageManagerServiceTest
+@Postsubmit
 @RunWith(AndroidJUnit4.class)
 public class PackageManagerServiceTest {
+
+    private static final String PACKAGE_NAME = "com.android.frameworks.servicestests";
+
+    private static final String TEST_DATA_PATH = "/data/local/tmp/servicestests/";
+    private static final String TEST_APP_APK = "StubTestApp.apk";
+    private static final String TEST_PKG_NAME = "com.android.servicestests.apps.stubapp";
+
+    private IPackageManager mIPackageManager;
+
     @Before
     public void setUp() throws Exception {
+        mIPackageManager = AppGlobals.getPackageManager();
     }
 
     @After
@@ -509,6 +530,11 @@
         for (Method m : coreMethods) {
             if (m != null) {
                 final String name = "ComputerEngine." + displayName(m);
+                if (name.contains(".lambda$static")) {
+                    // skip static lambda function
+                    continue;
+                }
+
                 final int modifiers = m.getModifiers();
                 if (isPrivate(modifiers)) {
                     // Okay
@@ -598,4 +624,138 @@
         Collections.sort(knownPackageIds);
         return knownPackageIds;
     }
+
+    @Test
+    public void testInstallReason_afterUpdate_keepUnchanged() throws Exception {
+        final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK);
+        try {
+            // Try to install test APK with reason INSTALL_REASON_POLICY
+            runShellCommand("pm install --install-reason 1 " + testApk);
+            assertWithMessage("The install reason of test APK is incorrect.").that(
+                    mIPackageManager.getInstallReason(TEST_PKG_NAME,
+                            UserHandle.myUserId())).isEqualTo(PackageManager.INSTALL_REASON_POLICY);
+
+            // Try to update test APK with different reason INSTALL_REASON_USER
+            runShellCommand("pm install --install-reason 4 " + testApk);
+            assertWithMessage("The install reason should keep unchanged after update.").that(
+                    mIPackageManager.getInstallReason(TEST_PKG_NAME,
+                            UserHandle.myUserId())).isEqualTo(PackageManager.INSTALL_REASON_POLICY);
+        } finally {
+            runShellCommand("pm uninstall " + TEST_PKG_NAME);
+        }
+    }
+
+    @Test
+    public void testInstallReason_userRemainsUninstalled_keepUnknown() throws Exception {
+        Assume.assumeTrue(UserManager.supportsMultipleUsers());
+        final UserManager um = UserManager.get(
+                InstrumentationRegistry.getInstrumentation().getContext());
+        final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK);
+        int userId = UserHandle.USER_NULL;
+        try {
+            // Try to install test APK with reason INSTALL_REASON_POLICY
+            runShellCommand("pm install --install-reason 1 " + testApk);
+            assertWithMessage("The install reason of test APK is incorrect.").that(
+                    mIPackageManager.getInstallReason(TEST_PKG_NAME,
+                            UserHandle.myUserId())).isEqualTo(PackageManager.INSTALL_REASON_POLICY);
+
+            // Create and start the 2nd user.
+            userId = um.createUser("Test User", 0 /* flags */).getUserHandle().getIdentifier();
+            runShellCommand("am start-user -w " + userId);
+            // Since the test APK isn't installed on the 2nd user, the reason should be unknown.
+            assertWithMessage("The install reason in 2nd user should be unknown.").that(
+                    mIPackageManager.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo(
+                    PackageManager.INSTALL_REASON_UNKNOWN);
+
+            // Try to update test APK with different reason INSTALL_REASON_USER
+            runShellCommand("pm install --install-reason 4 " + testApk);
+            assertWithMessage("The install reason in 2nd user should keep unknown.").that(
+                    mIPackageManager.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo(
+                    PackageManager.INSTALL_REASON_UNKNOWN);
+        } finally {
+            runShellCommand("pm uninstall " + TEST_PKG_NAME);
+            if (userId != UserHandle.USER_NULL) {
+                um.removeUser(userId);
+            }
+        }
+    }
+
+    @Test
+    public void testInstallReason_installForAllUsers_sameReason() throws Exception {
+        Assume.assumeTrue(UserManager.supportsMultipleUsers());
+        final UserManager um = UserManager.get(
+                InstrumentationRegistry.getInstrumentation().getContext());
+        final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK);
+        int userId = UserHandle.USER_NULL;
+        try {
+            // Create and start the 2nd user.
+            userId = um.createUser("Test User", 0 /* flags */).getUserHandle().getIdentifier();
+            runShellCommand("am start-user -w " + userId);
+
+            // Try to install test APK to all users with reason INSTALL_REASON_POLICY
+            runShellCommand("pm install --install-reason 1 " + testApk);
+            assertWithMessage("The install reason is inconsistent across users.").that(
+                    mIPackageManager.getInstallReason(TEST_PKG_NAME,
+                            UserHandle.myUserId())).isEqualTo(
+                    mIPackageManager.getInstallReason(TEST_PKG_NAME, userId));
+        } finally {
+            runShellCommand("pm uninstall " + TEST_PKG_NAME);
+            if (userId != UserHandle.USER_NULL) {
+                um.removeUser(userId);
+            }
+        }
+    }
+
+    @Test
+    public void testInstallReason_installSeparately_withSeparatedReason() throws Exception {
+        Assume.assumeTrue(UserManager.supportsMultipleUsers());
+        final UserManager um = UserManager.get(
+                InstrumentationRegistry.getInstrumentation().getContext());
+        final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK);
+        int userId = UserHandle.USER_NULL;
+        try {
+            // Create and start the 2nd user.
+            userId = um.createUser("Test User", 0 /* flags */).getUserHandle().getIdentifier();
+            runShellCommand("am start-user -w " + userId);
+
+            // Try to install test APK on the current user with reason INSTALL_REASON_POLICY
+            runShellCommand("pm install --user cur --install-reason 1 " + testApk);
+            assertWithMessage("The install reason on the current user is incorrect.").that(
+                    mIPackageManager.getInstallReason(TEST_PKG_NAME,
+                            UserHandle.myUserId())).isEqualTo(PackageManager.INSTALL_REASON_POLICY);
+
+            // Try to install test APK on the 2nd user with reason INSTALL_REASON_USER
+            runShellCommand("pm install --user " + userId + " --install-reason 4 " + testApk);
+            assertWithMessage("The install reason on the 2nd user is incorrect.").that(
+                    mIPackageManager.getInstallReason(TEST_PKG_NAME, userId)).isEqualTo(
+                    PackageManager.INSTALL_REASON_USER);
+        } finally {
+            runShellCommand("pm uninstall " + TEST_PKG_NAME);
+            if (userId != UserHandle.USER_NULL) {
+                um.removeUser(userId);
+            }
+        }
+    }
+
+    @Test
+    public void testSetSplashScreenTheme_samePackage_succeeds() throws Exception {
+        mIPackageManager.setSplashScreenTheme(PACKAGE_NAME, null /* themeName */,
+                UserHandle.myUserId());
+        // Invoking setSplashScreenTheme on the same package shouldn't get any exception.
+    }
+
+    @Test
+    public void testSetSplashScreenTheme_differentPackage_fails() throws Exception {
+        final File testApk = new File(TEST_DATA_PATH, TEST_APP_APK);
+        try {
+            runShellCommand("pm install " + testApk);
+            mIPackageManager.setSplashScreenTheme(TEST_PKG_NAME, null /* themeName */,
+                    UserHandle.myUserId());
+            fail("setSplashScreenTheme did not throw SecurityException as expected");
+        } catch (SecurityException e) {
+            // expected
+        } finally {
+            runShellCommand("pm uninstall " + TEST_PKG_NAME);
+        }
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index 5d93e3d..a9a3469 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -25,6 +25,7 @@
 import static android.content.pm.parsing.ParsingPackageUtils.parsePublicKey;
 import static android.content.res.Resources.ID_NULL;
 
+import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.CoreMatchers.notNullValue;
@@ -46,6 +47,7 @@
 import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
 import android.util.ArraySet;
 import android.util.AtomicFile;
 import android.util.Log;
@@ -86,11 +88,11 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.CountDownLatch;
 
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PackageManagerSettingsTests {
@@ -1004,6 +1006,13 @@
         }
     }
 
+    private void verifyKeySetData(PackageKeySetData originalData, PackageKeySetData testData) {
+        assertThat(originalData.getProperSigningKeySet(),
+                equalTo(testData.getProperSigningKeySet()));
+        assertThat(originalData.getUpgradeKeySets(), is(testData.getUpgradeKeySets()));
+        assertThat(originalData.getAliases(), is(testData.getAliases()));
+    }
+
     private void verifySettingCopy(PackageSetting origPkgSetting, PackageSetting testPkgSetting) {
         assertThat(origPkgSetting, is(not(testPkgSetting)));
         assertThat(origPkgSetting.getAppId(), is(testPkgSetting.getAppId()));
@@ -1018,8 +1027,7 @@
         assertSame(origPkgSetting.getInstallSource(), testPkgSetting.getInstallSource());
         assertThat(origPkgSetting.isInstallPermissionsFixed(),
                 is(testPkgSetting.isInstallPermissionsFixed()));
-        assertSame(origPkgSetting.getKeySetData(), testPkgSetting.getKeySetData());
-        assertThat(origPkgSetting.getKeySetData(), is(testPkgSetting.getKeySetData()));
+        verifyKeySetData(origPkgSetting.getKeySetData(), testPkgSetting.getKeySetData());
         assertThat(origPkgSetting.getLastUpdateTime(), is(testPkgSetting.getLastUpdateTime()));
         assertSame(origPkgSetting.getLegacyNativeLibraryPath(),
                 testPkgSetting.getLegacyNativeLibraryPath());
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java
index b6d4b31..7e4474f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java
@@ -24,6 +24,7 @@
 import android.content.Context;
 import android.content.pm.Signature;
 import android.content.pm.SigningDetails;
+import android.platform.test.annotations.Presubmit;
 import android.util.TypedXmlPullParser;
 import android.util.Xml;
 
@@ -44,6 +45,7 @@
 import java.util.Map;
 import java.util.Set;
 
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 public class PackageSignaturesTest {
     private static final String TEST_RESOURCES_FOLDER = "PackageSignaturesTest";
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
index c9f3cb2..828d419c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java
@@ -28,6 +28,7 @@
 import android.content.pm.SuspendDialogInfo;
 import android.content.pm.overlay.OverlayPaths;
 import android.os.PersistableBundle;
+import android.platform.test.annotations.Presubmit;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 
@@ -41,6 +42,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PackageUserStateTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
index 1fff4f0..ecf7803 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageVerificationStateTest.java
@@ -18,8 +18,10 @@
 
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
 
+@Presubmit
 public class PackageVerificationStateTest extends AndroidTestCase {
     private static final int REQUIRED_UID = 1948;
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/RestrictionsSetTest.java b/services/tests/servicestests/src/com/android/server/pm/RestrictionsSetTest.java
index b73c9ea..e7adf7b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/RestrictionsSetTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/RestrictionsSetTest.java
@@ -28,6 +28,7 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.runner.AndroidJUnit4;
 
@@ -37,6 +38,7 @@
 import java.util.List;
 
 /** Test for {@link RestrictionsSet}. */
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 public class RestrictionsSetTest {
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index ec5228f..32a88bd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -95,13 +95,15 @@
 import android.os.Looper;
 import android.os.Process;
 import android.os.UserHandle;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
 import android.util.Log;
 import android.util.SparseArray;
 import android.util.TypedXmlPullParser;
 import android.util.TypedXmlSerializer;
 import android.util.Xml;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.frameworks.servicestests.R;
 import com.android.server.pm.ShortcutService.ConfigConstants;
 import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
@@ -135,6 +137,7 @@
  adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest1 \
  -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
+@Presubmit
 @SmallTest
 public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
index e92c849..57ada9b 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest10.java
@@ -15,10 +15,13 @@
  */
 package com.android.server.pm;
 
-import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils
-        .assertExpectException;
+import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.assertExpectException;
 import static com.android.server.pm.shortcutmanagertest.ShortcutManagerTestUtils.list;
 
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.LauncherActivityInfo;
@@ -26,9 +29,9 @@
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager;
 import android.os.Process;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
 
-import static org.mockito.Mockito.*;
+import androidx.test.filters.SmallTest;
 
 /**
  * Tests for {@link ShortcutManager#createShortcutResultIntent(ShortcutInfo)} and relevant APIs.
@@ -39,6 +42,7 @@
  adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest10 \
  -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
+@Presubmit
 @SmallTest
 public class ShortcutManagerTest10 extends BaseShortcutManagerTest {
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
index c8a4052..98fa2d6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest11.java
@@ -30,6 +30,7 @@
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.ShortcutInfo;
 import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
 
 import com.android.server.pm.ShortcutService.ConfigConstants;
 
@@ -42,6 +43,7 @@
  *
  atest -c com.android.server.pm.ShortcutManagerTest11
  */
+@Presubmit
 public class ShortcutManagerTest11 extends BaseShortcutManagerTest {
 
     private static final ShortcutQuery QUERY_MATCH_ALL = createShortcutQuery(
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest12.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest12.java
index bc2d256..bcd216d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest12.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest12.java
@@ -49,8 +49,11 @@
 
     @Override
     protected void tearDown() throws Exception {
-        setCaller(CALLING_PACKAGE_1, USER_0);
-        mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_0).removeAllShortcutsAsync();
+        if (mService.isAppSearchEnabled()) {
+            setCaller(CALLING_PACKAGE_1, USER_0);
+            mService.getPackageShortcutForTest(CALLING_PACKAGE_1, USER_0)
+                    .removeAllShortcutsAsync();
+        }
         super.tearDown();
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index 90a1277..408d2c5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -43,8 +43,10 @@
 import android.net.Uri;
 import android.os.PersistableBundle;
 import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
 import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.SmallTest;
+
+import androidx.test.filters.SmallTest;
 
 import com.android.frameworks.servicestests.R;
 import com.android.server.pm.ShortcutUser.PackageWithUser;
@@ -64,6 +66,7 @@
  adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest2 \
  -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
+@Presubmit
 @SmallTest
 public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
     // ShortcutInfo tests
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
index ba26f79..43e527c 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest3.java
@@ -21,7 +21,9 @@
 
 import android.content.ComponentName;
 import android.content.pm.ShortcutInfo;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
 
 import com.android.frameworks.servicestests.R;
 import com.android.server.pm.ShortcutService.ConfigConstants;
@@ -31,6 +33,7 @@
 /**
  * Tests related to shortcut rank auto-adjustment.
  */
+@Presubmit
 @SmallTest
 public class ShortcutManagerTest3 extends BaseShortcutManagerTest {
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
index 7546c43..11a2a8a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest4.java
@@ -24,15 +24,17 @@
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.PersistableBundle;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
 import android.util.Xml;
 
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+@Presubmit
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class ShortcutManagerTest4 extends BaseShortcutManagerTest {
@@ -134,4 +136,4 @@
                     });
         });
     }
-}
\ No newline at end of file
+}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java
index 203b2ca..400d3a8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest5.java
@@ -25,7 +25,9 @@
 import android.content.pm.ShortcutServiceInternal;
 import android.content.res.XmlResourceParser;
 import android.os.Looper;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
 
 import com.android.server.LocalServices;
 
@@ -38,6 +40,7 @@
  * All the tests here actually talks to the real IPackageManager, so we can't test complicated
  * cases.  Instead we just make sure they all work reasonably without at least crashing.
  */
+@Presubmit
 @SmallTest
 public class ShortcutManagerTest5 extends BaseShortcutManagerTest {
     private ShortcutService mShortcutService;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java
index 63df4bc..6c10bfd 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest6.java
@@ -15,12 +15,15 @@
  */
 package com.android.server.pm;
 
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
 
 /**
  * Tests for {@link ShortcutService#hasShortcutHostPermissionInner}, which includes
  * {@link ShortcutService#getDefaultLauncher}.
  */
+@Presubmit
 @SmallTest
 public class ShortcutManagerTest6 extends BaseShortcutManagerTest {
     public void testHasShortcutHostPermissionInner_with3pLauncher_complicated() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
index b21b049..b2fd8aa 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest7.java
@@ -33,7 +33,9 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
 
 import com.android.frameworks.servicestests.R;
 import com.android.server.pm.ShortcutService.ConfigConstants;
@@ -48,6 +50,7 @@
  *
  * Launcher related commands are tested in
  */
+@Presubmit
 @SmallTest
 public class ShortcutManagerTest7 extends BaseShortcutManagerTest {
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
index 58e00f2..2293808 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest8.java
@@ -40,11 +40,13 @@
 import android.content.pm.ShortcutManager;
 import android.graphics.drawable.Icon;
 import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
 import android.test.MoreAsserts;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 import android.util.Pair;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.frameworks.servicestests.R;
 
 import org.mockito.ArgumentCaptor;
@@ -63,6 +65,7 @@
  * - Reading icons from requested shortcuts.
  * - Invalid pre-approved token.
  */
+@Presubmit
 @SmallTest
 public class ShortcutManagerTest8 extends BaseShortcutManagerTest {
     private ShortcutRequestPinProcessor mProcessor;
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
index 55b4b93..a47a8df 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest9.java
@@ -32,7 +32,9 @@
 import android.content.pm.LauncherApps;
 import android.content.pm.LauncherApps.PinItemRequest;
 import android.os.UserHandle;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
 
 import org.mockito.ArgumentCaptor;
 
@@ -46,6 +48,7 @@
  adb shell am instrument -e class com.android.server.pm.ShortcutManagerTest9 \
  -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  */
+@Presubmit
 @SmallTest
 public class ShortcutManagerTest9 extends BaseShortcutManagerTest {
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
index 826a8d4..4af91c6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SuspendDialogInfoTest.java
@@ -24,6 +24,7 @@
 import static org.junit.Assert.assertNull;
 
 import android.content.pm.SuspendDialogInfo;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -31,6 +32,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class SuspendDialogInfoTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/TEST_MAPPING b/services/tests/servicestests/src/com/android/server/pm/TEST_MAPPING
new file mode 100644
index 0000000..85a73bb
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/pm/TEST_MAPPING
@@ -0,0 +1,41 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.pm."
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        }
+      ]
+    }
+  ],
+  "postsubmit": [
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.pm."
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Postsubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
index 7916bd3..a4afe09 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserLifecycleStressTest.java
@@ -24,6 +24,7 @@
 import android.content.pm.UserInfo;
 import android.os.RemoteException;
 import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -42,6 +43,7 @@
  * To run the test:
  * bit FrameworksServicesTests:com.android.server.pm.UserLifecycleStressTest
  */
+@Postsubmit
 @RunWith(AndroidJUnit4.class)
 @LargeTest
 public class UserLifecycleStressTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
index 35c513f..fdf94be 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceCreateProfileTest.java
@@ -27,6 +27,7 @@
 import android.os.ServiceSpecificException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.MediumTest;
@@ -48,6 +49,7 @@
  * runtest -c com.android.server.pm.UserManagerServiceCreateProfileTest frameworks-services
  * </pre>
  */
+@Postsubmit
 @RunWith(AndroidJUnit4.class)
 @MediumTest
 public class UserManagerServiceCreateProfileTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java
index b0423bf..1f4c9f8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceIdRecyclingTest.java
@@ -23,6 +23,7 @@
 import android.app.PropertyInvalidatedCache;
 import android.content.pm.UserInfo;
 import android.os.Looper;
+import android.platform.test.annotations.Postsubmit;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.MediumTest;
@@ -45,6 +46,7 @@
  * -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  * </pre>
  */
+@Postsubmit
 @RunWith(AndroidJUnit4.class)
 @MediumTest
 public class UserManagerServiceIdRecyclingTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
index 6c1c019..34b40c7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceTest.java
@@ -22,18 +22,20 @@
 import android.os.Parcelable;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
 import android.support.test.uiautomator.UiDevice;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.text.TextUtils;
 import android.util.AtomicFile;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
 
 import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
 
+@Postsubmit
 @SmallTest
 public class UserManagerServiceTest extends AndroidTestCase {
     private static String[] STRING_ARRAY = new String[] {"<tag", "<![CDATA["};
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
index dfc25e0..92fddc7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
@@ -46,6 +46,7 @@
 import android.os.Parcel;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
 import android.text.TextUtils;
 
 import androidx.test.InstrumentationRegistry;
@@ -69,6 +70,7 @@
  * runtest -c com.android.server.pm.UserManagerServiceUserInfoTest frameworks-services
  * </pre>
  */
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 @MediumTest
 public class UserManagerServiceUserInfoTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
index f1acc66..971b036 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserTypeTest.java
@@ -39,6 +39,7 @@
 import android.content.res.XmlResourceParser;
 import android.os.Bundle;
 import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
 import android.util.ArrayMap;
 
 import androidx.test.InstrumentationRegistry;
@@ -58,6 +59,7 @@
  *
  * <p>Run with: atest UserManagerServiceUserTypeTest
  */
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 @MediumTest
 public class UserManagerServiceUserTypeTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index b76c279..cf6165f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -35,14 +35,15 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
 import android.provider.Settings;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Slog;
 
 import androidx.annotation.Nullable;
 import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.google.common.collect.Range;
@@ -63,6 +64,7 @@
 import javax.annotation.concurrent.GuardedBy;
 
 /** Test {@link UserManager} functionality. */
+@Postsubmit
 @RunWith(AndroidJUnit4.class)
 public final class UserManagerTest {
     // Taken from UserManagerService
@@ -207,6 +209,65 @@
         assertThat(hasUser(user2.id)).isTrue();
     }
 
+    /**
+     * Tests that UserManager knows how many users can be created.
+     *
+     * We can only test this with regular secondary users, since some other user types have weird
+     * rules about when or if they count towards the max.
+     */
+    @MediumTest
+    @Test
+    public void testAddTooManyUsers() throws Exception {
+        final String userType = UserManager.USER_TYPE_FULL_SECONDARY;
+        final UserTypeDetails userTypeDetails = UserTypeFactory.getUserTypes().get(userType);
+
+        final int maxUsersForType = userTypeDetails.getMaxAllowed();
+        final int maxUsersOverall = UserManager.getMaxSupportedUsers();
+
+        int currentUsersOfType = 0;
+        int currentUsersOverall = 0;
+        final List<UserInfo> userList = mUserManager.getAliveUsers();
+        for (UserInfo user : userList) {
+            currentUsersOverall++;
+            if (userType.equals(user.userType)) {
+                currentUsersOfType++;
+            }
+        }
+
+        final int remainingUserType = maxUsersForType == UserTypeDetails.UNLIMITED_NUMBER_OF_USERS ?
+                Integer.MAX_VALUE : maxUsersForType - currentUsersOfType;
+        final int remainingOverall = maxUsersOverall - currentUsersOverall;
+        final int remaining = Math.min(remainingUserType, remainingOverall);
+
+        Slog.v(TAG, "maxUsersForType=" + maxUsersForType
+                + ", maxUsersOverall=" + maxUsersOverall
+                + ", currentUsersOfType=" + currentUsersOfType
+                + ", currentUsersOverall=" + currentUsersOverall
+                + ", remaining=" + remaining);
+
+        assumeTrue("Device supports too many users for this test to be practical", remaining < 20);
+
+        int usersAdded;
+        for (usersAdded = 0; usersAdded < remaining; usersAdded++) {
+            Slog.v(TAG, "Adding user " + usersAdded);
+            assertThat(mUserManager.canAddMoreUsers()).isTrue();
+            assertThat(mUserManager.canAddMoreUsers(userType)).isTrue();
+
+            final UserInfo user = createUser("User " + usersAdded, userType, 0);
+            assertThat(user).isNotNull();
+            assertThat(hasUser(user.id)).isTrue();
+        }
+        Slog.v(TAG, "Added " + usersAdded + " users.");
+
+        assertWithMessage("Still thinks more users of that type can be added")
+                .that(mUserManager.canAddMoreUsers(userType)).isFalse();
+        if (currentUsersOverall + usersAdded >= maxUsersOverall) {
+            assertThat(mUserManager.canAddMoreUsers()).isFalse();
+        }
+
+        assertThat(createUser("User beyond", userType, 0)).isNull();
+    }
+
     @MediumTest
     @Test
     public void testRemoveUser() throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
index ddf0cd0..07a5303 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserRestrictionsUtilsTest.java
@@ -22,10 +22,12 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
 import android.test.AndroidTestCase;
-import android.test.suitebuilder.annotation.SmallTest;
 import android.util.SparseArray;
 
+import androidx.test.filters.SmallTest;
+
 /**
  * Tests for {@link com.android.server.pm.UserRestrictionsUtils}.
  *
@@ -37,6 +39,7 @@
      -w com.android.frameworks.servicestests/androidx.test.runner.AndroidJUnitRunner
  * </pre>
  */
+@Presubmit
 @SmallTest
 public class UserRestrictionsUtilsTest extends AndroidTestCase {
     public void testNonNull() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
index b11bb85..ba7a103 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
@@ -43,6 +43,7 @@
 import android.os.Looper;
 import android.os.SystemProperties;
 import android.os.UserManager;
+import android.platform.test.annotations.Postsubmit;
 import android.support.test.uiautomator.UiDevice;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -76,6 +77,7 @@
  * atest com.android.server.pm.UserSystemPackageInstallerTest
  * </pre>
  */
+@Postsubmit
 @RunWith(AndroidJUnit4.class)
 @MediumTest
 public class UserSystemPackageInstallerTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java b/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java
index b2c3002..95af1e1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/WatchedIntentHandlingTest.java
@@ -20,6 +20,7 @@
 
 import android.content.ComponentName;
 import android.content.IntentFilter;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
@@ -29,6 +30,7 @@
 
 import java.util.Iterator;
 
+@Presubmit
 @SmallTest
 public class WatchedIntentHandlingTest {
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
index fdb6e9f5..a16ecb1 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/ArtStatsLogUtilsTest.java
@@ -18,6 +18,8 @@
 
 import static org.mockito.Mockito.inOrder;
 
+import android.platform.test.annotations.Presubmit;
+
 import com.android.internal.art.ArtStatsLog;
 import com.android.server.pm.dex.ArtStatsLogUtils.ArtStatsLogger;
 
@@ -44,6 +46,7 @@
  *
  * Run with "atest ArtStatsLogUtilsTest".
  */
+@Presubmit
 @RunWith(JUnit4.class)
 public final class ArtStatsLogUtilsTest {
     private static final String TAG = ArtStatsLogUtilsTest.class.getSimpleName();
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
index 2a7a2ff..b7b55ba 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
@@ -30,6 +30,7 @@
 import android.content.pm.parsing.result.ParseResult;
 import android.content.pm.parsing.result.ParseTypeImpl;
 import android.os.FileUtils;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -61,6 +62,7 @@
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
 
+@Presubmit
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class DexMetadataHelperTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
index bc84e35..d5893c8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptOptionsTests.java
@@ -23,6 +23,8 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import android.platform.test.annotations.Presubmit;
+
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -32,6 +34,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class DexoptOptionsTests {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
index 34cefec..1dcb0b7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
@@ -24,6 +24,7 @@
 
 import android.content.pm.SharedLibraryInfo;
 import android.content.pm.parsing.ParsingPackage;
+import android.platform.test.annotations.Presubmit;
 import android.util.SparseArray;
 
 import androidx.test.filters.SmallTest;
@@ -46,6 +47,7 @@
 import java.util.Collections;
 import java.util.List;
 
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class DexoptUtilsTest {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DynamicCodeLoggerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DynamicCodeLoggerTests.java
index 7992ba3..d55f967 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DynamicCodeLoggerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DynamicCodeLoggerTests.java
@@ -31,6 +31,7 @@
 import android.content.pm.PackageInfo;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -51,6 +52,7 @@
 import org.mockito.quality.Strictness;
 import org.mockito.stubbing.Stubber;
 
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class DynamicCodeLoggerTests {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
index 3450710..c98e7c3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDexUsageTests.java
@@ -28,6 +28,7 @@
 import static org.junit.Assert.fail;
 
 import android.os.Build;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
@@ -49,6 +50,7 @@
 import java.util.Map;
 import java.util.Set;
 
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PackageDexUsageTests {
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java
index f4cdc8c..e075379 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/PackageDynamicCodeLoadingTests.java
@@ -30,6 +30,8 @@
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import android.platform.test.annotations.Presubmit;
+
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -50,6 +52,7 @@
 import java.util.Objects;
 import java.util.Set;
 
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class PackageDynamicCodeLoadingTests {
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
index 51c268e..4059a49 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
@@ -16,17 +16,18 @@
 
 package com.android.server.pm.parsing
 
+import android.Manifest
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageInfo
 import android.content.pm.PackageManager
 import android.content.pm.PackageParser
 import android.platform.test.annotations.Postsubmit
+import com.android.internal.util.ArrayUtils
 import com.android.server.pm.parsing.AndroidPackageInfoFlagBehaviorTest.Companion.Param.Companion.appInfo
 import com.android.server.pm.parsing.AndroidPackageInfoFlagBehaviorTest.Companion.Param.Companion.pkgInfo
 import com.android.server.pm.parsing.pkg.AndroidPackage
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
-import org.junit.Ignore
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
@@ -91,9 +92,18 @@
                     listOf(it.configPreferences, it.reqFeatures, it.featureGroups)
                 },
                 pkgInfo(PackageManager.GET_PERMISSIONS) {
-                    listOf(it.permissions, it.requestedPermissions, it.requestedPermissionsFlags)
+                    listOf(
+                        it.permissions,
+                        // Strip compatibility permission added in T
+                        it.requestedPermissions?.filter { x ->
+                            x != Manifest.permission.POST_NOTIFICATIONS
+                        }?.ifEmpty { null }?.toTypedArray(),
+                        // Strip the flag from compatibility permission added in T
+                        it.requestedPermissionsFlags?.filterIndexed { index, _ ->
+                            index != ArrayUtils.indexOf(it.requestedPermissions,
+                                                        Manifest.permission.POST_NOTIFICATIONS)
+                        }?.ifEmpty { null }?.toTypedArray())
                 },
-
                 appInfo(PackageManager.GET_META_DATA) { listOf(it.metaData) },
                 appInfo(PackageManager.GET_SHARED_LIBRARY_FILES) {
                     listOf(it.sharedLibraryFiles, it.sharedLibraryFiles)
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
index 39d5388..122661e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
@@ -16,6 +16,7 @@
 
 package com.android.server.pm.parsing
 
+import android.Manifest
 import android.content.Context
 import android.content.pm.ActivityInfo
 import android.content.pm.ApplicationInfo
@@ -34,6 +35,7 @@
 import android.os.Process
 import android.util.SparseArray
 import androidx.test.platform.app.InstrumentationRegistry
+import com.android.internal.util.ArrayUtils
 import com.android.server.pm.PackageManagerService
 import com.android.server.pm.parsing.pkg.AndroidPackage
 import com.android.server.pm.pkg.PackageStateInternal
@@ -329,7 +331,10 @@
             .ignored("Update for fixing b/128526493 and the testing is no longer valid")}
             enabled=${this.enabled}
             exported=${this.exported}
-            flags=${Integer.toBinaryString(this.flags)}
+            flags=${Integer.toBinaryString(
+                // Strip flag added in T
+                this.flags and (ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES.inv()))
+            }
             icon=${this.icon}
             labelRes=${this.labelRes}
             launchMode=${this.launchMode}
@@ -501,13 +506,22 @@
             receivers=${this.receivers?.joinToString { it.dumpToString() }
             .ignored("Checked separately in test")}
             reqFeatures=${this.reqFeatures?.joinToString { it.dumpToString() }}
-            requestedPermissions=${this.requestedPermissions?.contentToString()}
+            requestedPermissions=${
+                // Strip compatibility permission added in T
+                this.requestedPermissions?.filter { x ->
+                    x != Manifest.permission.POST_NOTIFICATIONS
+                }?.ifEmpty { null }?.joinToString()
+            }
             requestedPermissionsFlags=${
-                this.requestedPermissionsFlags?.map {
+                // Strip the flag from compatibility permission added in T
+                this.requestedPermissionsFlags?.filterIndexed { index, _ ->
+                    index != ArrayUtils.indexOf(requestedPermissions,
+                                                Manifest.permission.POST_NOTIFICATIONS)
+                }?.map {
                     // Newer flags are stripped
                     it and (PackageInfo.REQUESTED_PERMISSION_REQUIRED
                             or PackageInfo.REQUESTED_PERMISSION_GRANTED)
-                }?.joinToString()
+                }?.ifEmpty { null }?.joinToString()
             }
             requiredAccountType=${this.requiredAccountType}
             requiredForAllUsers=${this.requiredForAllUsers}
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt
index c4aa862..f530421 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParsingDeferErrorTest.kt
@@ -21,6 +21,7 @@
 import android.content.pm.parsing.ParsingPackage
 import android.content.pm.parsing.ParsingPackageUtils
 import android.content.pm.parsing.result.ParseResult
+import android.platform.test.annotations.Presubmit
 import androidx.test.InstrumentationRegistry
 import com.android.frameworks.servicestests.R
 import com.google.common.truth.Truth.assertThat
@@ -36,6 +37,7 @@
  *
  * This verifies these failures when the APK targets R.
  */
+@Presubmit
 class PackageParsingDeferErrorTest {
 
     companion object {
diff --git a/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java
index 3261dfa..3551af8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/permission/LegacyPermissionManagerServiceTest.java
@@ -31,6 +31,7 @@
 import android.content.pm.PackageManager;
 import android.os.Build;
 import android.os.Process;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.runner.AndroidJUnit4;
@@ -41,6 +42,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 public class LegacyPermissionManagerServiceTest {
     private static final int SYSTEM_UID = 1000;
diff --git a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
index 6e3f754..a3223d6d 100644
--- a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
@@ -34,6 +34,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.ServiceManager;
+import android.os.VibrationAttributes;
 import android.os.Vibrator;
 import android.os.test.TestLooper;
 import android.provider.Settings;
@@ -108,7 +109,7 @@
         mTestLooper.dispatchAll();
 
         // THEN the device vibrates once
-        verify(mVibrator, times(1)).vibrate(any(), any());
+        verify(mVibrator, times(1)).vibrate(any(), any(VibrationAttributes.class));
     }
 
     @Test
@@ -123,7 +124,7 @@
         mTestLooper.dispatchAll();
 
         // THEN the device doesn't vibrate
-        verify(mVibrator, never()).vibrate(any(), any());
+        verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class));
     }
 
     @Test
@@ -138,7 +139,7 @@
         mTestLooper.dispatchAll();
 
         // THEN the device vibrates once
-        verify(mVibrator, times(1)).vibrate(any(), any());
+        verify(mVibrator, times(1)).vibrate(any(), any(VibrationAttributes.class));
     }
 
     @Test
@@ -153,7 +154,7 @@
         mTestLooper.dispatchAll();
 
         // THEN the device doesn't vibrate
-        verify(mVibrator, never()).vibrate(any(), any());
+        verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class));
     }
 
     @Test
@@ -171,7 +172,7 @@
         mTestLooper.dispatchAll();
 
         // THEN the device doesn't vibrate
-        verify(mVibrator, never()).vibrate(any(), any());
+        verify(mVibrator, never()).vibrate(any(), any(VibrationAttributes.class));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/ReferenceWithHistoryTest.java b/services/tests/servicestests/src/com/android/server/timedetector/ReferenceWithHistoryTest.java
index ce72499..d5d2cbd 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/ReferenceWithHistoryTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/ReferenceWithHistoryTest.java
@@ -17,17 +17,19 @@
 package com.android.server.timedetector;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.util.IndentingPrintWriter;
 
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.timezonedetector.ReferenceWithHistory;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.io.StringWriter;
+import java.util.Arrays;
 
 @RunWith(AndroidJUnit4.class)
 public class ReferenceWithHistoryTest {
@@ -41,31 +43,34 @@
 
         // Check unset behavior.
         compareGet(referenceWithHistory, reference, null);
-        assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+        assertDumpContent(referenceWithHistory);
         compareToString(referenceWithHistory, reference, "null");
 
         // Try setting null.
         setAndCompareReturnValue(referenceWithHistory, reference, null);
         compareGet(referenceWithHistory, reference, null);
-        assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+        assertDumpContent(referenceWithHistory, new DumpLine(0, "null"));
         compareToString(referenceWithHistory, reference, "null");
 
         // Try setting a non-null value.
         setAndCompareReturnValue(referenceWithHistory, reference, "Foo");
         compareGet(referenceWithHistory, reference, "Foo");
-        assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+        assertDumpContent(referenceWithHistory,
+                new DumpLine(0, "null"), new DumpLine(1, "Foo"));
         compareToString(referenceWithHistory, reference, "Foo");
 
         // Try setting null again.
-        setAndCompareReturnValue(referenceWithHistory, reference, "Foo");
-        compareGet(referenceWithHistory, reference, "Foo");
-        assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
-        compareToString(referenceWithHistory, reference, "Foo");
+        setAndCompareReturnValue(referenceWithHistory, reference, null);
+        compareGet(referenceWithHistory, reference, null);
+        assertDumpContent(referenceWithHistory,
+                new DumpLine(1, "Foo"), new DumpLine(2, "null"));
+        compareToString(referenceWithHistory, reference, "null");
 
         // Try a non-null value again.
         setAndCompareReturnValue(referenceWithHistory, reference, "Bar");
         compareGet(referenceWithHistory, reference, "Bar");
-        assertNotNull(dumpReferenceWithHistory(referenceWithHistory));
+        assertDumpContent(referenceWithHistory,
+                new DumpLine(2, "null"), new DumpLine(3, "Bar"));
         compareToString(referenceWithHistory, reference, "Bar");
     }
 
@@ -132,11 +137,54 @@
         assertEquals(expected, referenceWithHistory.toString());
     }
 
-    private static String dumpReferenceWithHistory(ReferenceWithHistory<?> referenceWithHistory) {
+    private static void assertDumpContent(
+            ReferenceWithHistory<?> referenceWithHistory, DumpLine... expectedLines) {
+        String[] actualLines = dumpReferenceWithHistory(referenceWithHistory);
+
+        if (expectedLines.length == 0) {
+            String expectedEmptyOutput = "{Empty}";
+            assertEquals(expectedEmptyOutput, 1, actualLines.length);
+            assertEquals(expectedEmptyOutput, actualLines[0]);
+        } else {
+            assertEquals("Expected=" + Arrays.toString(expectedLines)
+                            + ", actual=" + Arrays.toString(actualLines),
+                    expectedLines.length, actualLines.length);
+            for (int i = 0; i < expectedLines.length; i++) {
+                DumpLine expectedLine = expectedLines[i];
+                String actualLine = actualLines[i];
+                assertTrue("i=" + i + ", expected=" + expectedLine + ", actual=" + actualLine,
+                        actualLine.startsWith(Integer.toString(expectedLine.mIndex)));
+                assertTrue("i=" + i + ", expected=" + expectedLine + ", actual=" + actualLine,
+                        actualLine.endsWith(expectedLine.mLine));
+            }
+        }
+    }
+
+    private static String[] dumpReferenceWithHistory(ReferenceWithHistory<?> referenceWithHistory) {
         StringWriter stringWriter = new StringWriter();
         try (IndentingPrintWriter ipw = new IndentingPrintWriter(stringWriter, " ")) {
             referenceWithHistory.dump(ipw);
-            return stringWriter.toString();
+            return stringWriter.toString().split("\n");
+        }
+    }
+
+    /** An expected line of {@link ReferenceWithHistory#dump} output. */
+    private static class DumpLine {
+
+        final int mIndex;
+        final String mLine;
+
+        DumpLine(int index, String line) {
+            mIndex = index;
+            mLine = line;
+        }
+
+        @Override
+        public String toString() {
+            return "DumpLine{"
+                    + "mIndex=" + mIndex
+                    + ", mLine='" + mLine + '\''
+                    + '}';
         }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
index 117680b..6ee6020c 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/ConfigurationInternalTest.java
@@ -48,13 +48,14 @@
                 .setUserConfigAllowed(true)
                 .setTelephonyDetectionFeatureSupported(true)
                 .setGeoDetectionFeatureSupported(true)
-                .setAutoDetectionEnabled(true)
-                .setLocationEnabled(true)
-                .setGeoDetectionEnabled(true)
+                .setTelephonyFallbackSupported(false)
+                .setAutoDetectionEnabledSetting(true)
+                .setLocationEnabledSetting(true)
+                .setGeoDetectionEnabledSetting(true)
                 .build();
         {
             ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
-                    .setAutoDetectionEnabled(true)
+                    .setAutoDetectionEnabledSetting(true)
                     .build();
             assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
             assertTrue(autoOnConfig.getGeoDetectionEnabledSetting());
@@ -79,7 +80,7 @@
 
         {
             ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
-                    .setAutoDetectionEnabled(false)
+                    .setAutoDetectionEnabledSetting(false)
                     .build();
             assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
             assertTrue(autoOffConfig.getGeoDetectionEnabledSetting());
@@ -110,13 +111,14 @@
                 .setUserConfigAllowed(false)
                 .setTelephonyDetectionFeatureSupported(true)
                 .setGeoDetectionFeatureSupported(true)
-                .setAutoDetectionEnabled(true)
-                .setLocationEnabled(true)
-                .setGeoDetectionEnabled(true)
+                .setTelephonyFallbackSupported(false)
+                .setAutoDetectionEnabledSetting(true)
+                .setLocationEnabledSetting(true)
+                .setGeoDetectionEnabledSetting(true)
                 .build();
         {
             ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
-                    .setAutoDetectionEnabled(true)
+                    .setAutoDetectionEnabledSetting(true)
                     .build();
             assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
             assertTrue(autoOnConfig.getGeoDetectionEnabledSetting());
@@ -142,7 +144,7 @@
 
         {
             ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
-                    .setAutoDetectionEnabled(false)
+                    .setAutoDetectionEnabledSetting(false)
                     .build();
             assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
             assertTrue(autoOffConfig.getGeoDetectionEnabledSetting());
@@ -174,13 +176,14 @@
                 .setUserConfigAllowed(true)
                 .setTelephonyDetectionFeatureSupported(false)
                 .setGeoDetectionFeatureSupported(false)
-                .setAutoDetectionEnabled(true)
-                .setLocationEnabled(true)
-                .setGeoDetectionEnabled(true)
+                .setTelephonyFallbackSupported(false)
+                .setAutoDetectionEnabledSetting(true)
+                .setLocationEnabledSetting(true)
+                .setGeoDetectionEnabledSetting(true)
                 .build();
         {
             ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
-                    .setAutoDetectionEnabled(true)
+                    .setAutoDetectionEnabledSetting(true)
                     .build();
             assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
             assertTrue(autoOnConfig.getGeoDetectionEnabledSetting());
@@ -203,7 +206,7 @@
         }
         {
             ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
-                    .setAutoDetectionEnabled(false)
+                    .setAutoDetectionEnabledSetting(false)
                     .build();
             assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
             assertTrue(autoOffConfig.getGeoDetectionEnabledSetting());
@@ -236,13 +239,14 @@
                 .setUserConfigAllowed(true)
                 .setTelephonyDetectionFeatureSupported(true)
                 .setGeoDetectionFeatureSupported(false)
-                .setAutoDetectionEnabled(true)
-                .setLocationEnabled(true)
-                .setGeoDetectionEnabled(true)
+                .setTelephonyFallbackSupported(false)
+                .setAutoDetectionEnabledSetting(true)
+                .setLocationEnabledSetting(true)
+                .setGeoDetectionEnabledSetting(true)
                 .build();
         {
             ConfigurationInternal autoOnConfig = new ConfigurationInternal.Builder(baseConfig)
-                    .setAutoDetectionEnabled(true)
+                    .setAutoDetectionEnabledSetting(true)
                     .build();
             assertTrue(autoOnConfig.getAutoDetectionEnabledSetting());
             assertTrue(autoOnConfig.getGeoDetectionEnabledSetting());
@@ -266,7 +270,7 @@
         }
         {
             ConfigurationInternal autoOffConfig = new ConfigurationInternal.Builder(baseConfig)
-                    .setAutoDetectionEnabled(false)
+                    .setAutoDetectionEnabledSetting(false)
                     .build();
             assertFalse(autoOffConfig.getAutoDetectionEnabledSetting());
             assertTrue(autoOffConfig.getGeoDetectionEnabledSetting());
@@ -288,4 +292,18 @@
             assertTrue(configuration.isGeoDetectionEnabled());
         }
     }
+
+    @Test
+    public void test_telephonyFallbackSupported() {
+        ConfigurationInternal config = new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
+                .setUserConfigAllowed(true)
+                .setTelephonyDetectionFeatureSupported(true)
+                .setGeoDetectionFeatureSupported(false)
+                .setTelephonyFallbackSupported(true)
+                .setAutoDetectionEnabledSetting(true)
+                .setLocationEnabledSetting(true)
+                .setGeoDetectionEnabledSetting(true)
+                .build();
+        assertTrue(config.isTelephonyFallbackSupported());
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java
new file mode 100644
index 0000000..a97ad8c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeServiceConfigAccessor.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2021 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.timezonedetector;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.app.time.TimeZoneCapabilities;
+import android.app.time.TimeZoneCapabilitiesAndConfig;
+import android.app.time.TimeZoneConfiguration;
+
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+/** A partially implemented, fake implementation of ServiceConfigAccessor for tests. */
+class FakeServiceConfigAccessor implements ServiceConfigAccessor {
+
+    private final List<ConfigurationChangeListener> mConfigurationInternalChangeListeners =
+            new ArrayList<>();
+    private ConfigurationInternal mConfigurationInternal;
+
+    @Override
+    public void addConfigurationInternalChangeListener(ConfigurationChangeListener listener) {
+        mConfigurationInternalChangeListeners.add(listener);
+    }
+
+    @Override
+    public void removeConfigurationInternalChangeListener(ConfigurationChangeListener listener) {
+        mConfigurationInternalChangeListeners.remove(listener);
+    }
+
+    @Override
+    public ConfigurationInternal getCurrentUserConfigurationInternal() {
+        return mConfigurationInternal;
+    }
+
+    @Override
+    public boolean updateConfiguration(
+            @UserIdInt int userID, @NonNull TimeZoneConfiguration requestedChanges) {
+        assertNotNull(mConfigurationInternal);
+        assertNotNull(requestedChanges);
+
+        // Simulate the real strategy's behavior: the new configuration will be updated to be the
+        // old configuration merged with the new if the user has the capability to up the settings.
+        // Then, if the configuration changed, the change listener is invoked.
+        TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+                mConfigurationInternal.createCapabilitiesAndConfig();
+        TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
+        TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
+        TimeZoneConfiguration newConfiguration =
+                capabilities.tryApplyConfigChanges(configuration, requestedChanges);
+        if (newConfiguration == null) {
+            return false;
+        }
+
+        if (!newConfiguration.equals(capabilitiesAndConfig.getConfiguration())) {
+            mConfigurationInternal = mConfigurationInternal.merge(newConfiguration);
+
+            // Note: Unlike the real strategy, the listeners are invoked synchronously.
+            simulateConfigurationChangeForTests();
+        }
+        return true;
+    }
+
+    void initializeConfiguration(ConfigurationInternal configurationInternal) {
+        mConfigurationInternal = configurationInternal;
+    }
+
+    void simulateConfigurationChangeForTests() {
+        for (ConfigurationChangeListener listener : mConfigurationInternalChangeListeners) {
+            listener.onChange();
+        }
+    }
+
+    @Override
+    public ConfigurationInternal getConfigurationInternal(int userId) {
+        assertEquals("Multi-user testing not supported currently",
+                userId, mConfigurationInternal.getUserId());
+        return mConfigurationInternal;
+    }
+
+    @Override
+    public void addLocationTimeZoneManagerConfigListener(ConfigurationChangeListener listener) {
+        failUnimplemented();
+    }
+
+    @Override
+    public boolean isTelephonyTimeZoneDetectionFeatureSupported() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public boolean isGeoTimeZoneDetectionFeatureSupportedInConfig() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public boolean isGeoTimeZoneDetectionFeatureSupported() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public String getPrimaryLocationTimeZoneProviderPackageName() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public void setTestPrimaryLocationTimeZoneProviderPackageName(
+            String testPrimaryLocationTimeZoneProviderPackageName) {
+        failUnimplemented();
+    }
+
+    @Override
+    public boolean isTestPrimaryLocationTimeZoneProvider() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public String getSecondaryLocationTimeZoneProviderPackageName() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public void setTestSecondaryLocationTimeZoneProviderPackageName(
+            String testSecondaryLocationTimeZoneProviderPackageName) {
+        failUnimplemented();
+    }
+
+    @Override
+    public boolean isTestSecondaryLocationTimeZoneProvider() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public void setRecordStateChangesForTests(boolean enabled) {
+        failUnimplemented();
+    }
+
+    @Override
+    public boolean getRecordStateChangesForTests() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public @ProviderMode String getPrimaryLocationTimeZoneProviderMode() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public @ProviderMode String getSecondaryLocationTimeZoneProviderMode() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public boolean isGeoDetectionEnabledForUsersByDefault() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public Optional<Boolean> getGeoDetectionSettingEnabledOverride() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public Duration getLocationTimeZoneProviderInitializationTimeout() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public Duration getLocationTimeZoneProviderInitializationTimeoutFuzz() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public Duration getLocationTimeZoneUncertaintyDelay() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public Duration getLocationTimeZoneProviderEventFilteringAgeThreshold() {
+        return failUnimplemented();
+    }
+
+    @Override
+    public void resetVolatileTestConfig() {
+        failUnimplemented();
+    }
+
+    @SuppressWarnings("UnusedReturnValue")
+    private static <T> T failUnimplemented() {
+        fail("Unimplemented");
+        return null;
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
index 51f627a..2d0dca2 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/FakeTimeZoneDetectorStrategy.java
@@ -16,88 +16,21 @@
 package com.android.server.timezonedetector;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
-import android.app.time.TimeZoneCapabilities;
-import android.app.time.TimeZoneCapabilitiesAndConfig;
-import android.app.time.TimeZoneConfiguration;
 import android.app.timezonedetector.ManualTimeZoneSuggestion;
 import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
 import android.util.IndentingPrintWriter;
 
-import java.util.ArrayList;
-import java.util.List;
-
 class FakeTimeZoneDetectorStrategy implements TimeZoneDetectorStrategy {
 
-    private ConfigurationChangeListener mConfigurationChangeListener;
-
-    // Fake state
-    private ConfigurationInternal mConfigurationInternal;
-
     // Call tracking.
     private GeolocationTimeZoneSuggestion mLastGeolocationSuggestion;
     private ManualTimeZoneSuggestion mLastManualSuggestion;
     private TelephonyTimeZoneSuggestion mLastTelephonySuggestion;
     private boolean mDumpCalled;
-    private final List<Dumpable> mDumpables = new ArrayList<>();
-
-    @Override
-    public void addConfigChangeListener(@NonNull ConfigurationChangeListener listener) {
-        if (mConfigurationChangeListener != null) {
-            fail("Fake only supports one listener");
-        }
-        mConfigurationChangeListener = listener;
-    }
-
-    @Override
-    public ConfigurationInternal getConfigurationInternal(int userId) {
-        if (mConfigurationInternal.getUserId() != userId) {
-            fail("Fake only supports one user");
-        }
-        return mConfigurationInternal;
-    }
-
-    @Override
-    public ConfigurationInternal getCurrentUserConfigurationInternal() {
-        return mConfigurationInternal;
-    }
-
-    @Override
-    public boolean updateConfiguration(
-            @UserIdInt int userID, @NonNull TimeZoneConfiguration requestedChanges) {
-        assertNotNull(mConfigurationInternal);
-        assertNotNull(requestedChanges);
-
-        // Simulate the real strategy's behavior: the new configuration will be updated to be the
-        // old configuration merged with the new if the user has the capability to up the settings.
-        // Then, if the configuration changed, the change listener is invoked.
-        TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
-                mConfigurationInternal.createCapabilitiesAndConfig();
-        TimeZoneCapabilities capabilities = capabilitiesAndConfig.getCapabilities();
-        TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
-        TimeZoneConfiguration newConfiguration =
-                capabilities.tryApplyConfigChanges(configuration, requestedChanges);
-        if (newConfiguration == null) {
-            return false;
-        }
-
-        if (!newConfiguration.equals(capabilitiesAndConfig.getConfiguration())) {
-            mConfigurationInternal = mConfigurationInternal.merge(newConfiguration);
-
-            // Note: Unlike the real strategy, the listeners is invoked synchronously.
-            mConfigurationChangeListener.onChange();
-        }
-        return true;
-    }
-
-    public void simulateConfigurationChangeForTests() {
-        mConfigurationChangeListener.onChange();
-    }
 
     @Override
     public void suggestGeolocationTimeZone(GeolocationTimeZoneSuggestion timeZoneSuggestion) {
@@ -118,24 +51,20 @@
     }
 
     @Override
+    public void enableTelephonyTimeZoneFallback() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
     public MetricsTimeZoneDetectorState generateMetricsState() {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public void addDumpable(Dumpable dumpable) {
-        mDumpables.add(dumpable);
-    }
-
-    @Override
     public void dump(IndentingPrintWriter pw, String[] args) {
         mDumpCalled = true;
     }
 
-    void initializeConfiguration(ConfigurationInternal configurationInternal) {
-        mConfigurationInternal = configurationInternal;
-    }
-
     void resetCallTracking() {
         mLastGeolocationSuggestion = null;
         mLastManualSuggestion = null;
@@ -159,8 +88,4 @@
     void verifyDumpCalled() {
         assertTrue(mDumpCalled);
     }
-
-    void verifyHasDumpable(Dumpable expected) {
-        assertTrue(mDumpables.contains(expected));
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TestState.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TestState.java
index 97b8360..97095c4 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TestState.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TestState.java
@@ -20,6 +20,7 @@
 import static org.junit.Assert.assertTrue;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 
 /**
  * A test support class used for tracking a piece of state in test objects like fakes and mocks.
@@ -79,6 +80,11 @@
         assertEquals(expectedCount, getChangeCount());
     }
 
+    /** Asserts the value has been {@link #set} to the expected values in the order given. */
+    public void assertChanges(T... expected) {
+        assertEquals(Arrays.asList(expected), mValues);
+    }
+
     /**
      * Returns the latest value passed to {@link #set}. If {@link #set} hasn't been called then the
      * initial value is returned.
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
index 5864620..c5bab76 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorInternalImplTest.java
@@ -16,7 +16,6 @@
 
 package com.android.server.timezonedetector;
 
-import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.mock;
 
 import android.content.Context;
@@ -77,28 +76,6 @@
         mFakeTimeZoneDetectorStrategy.verifySuggestGeolocationTimeZoneCalled(timeZoneSuggestion);
     }
 
-    @Test
-    public void testAddDumpable() throws Exception {
-        Dumpable stubbedDumpable = mock(Dumpable.class);
-
-        mTimeZoneDetectorInternal.addDumpable(stubbedDumpable);
-        mTestHandler.assertTotalMessagesEnqueued(0);
-
-        mFakeTimeZoneDetectorStrategy.verifyHasDumpable(stubbedDumpable);
-    }
-
-    @Test
-    public void testAddConfigurationListener() throws Exception {
-        boolean[] changeCalled = new boolean[2];
-        mTimeZoneDetectorInternal.addConfigurationListener(() -> changeCalled[0] = true);
-        mTimeZoneDetectorInternal.addConfigurationListener(() -> changeCalled[1] = true);
-
-        mFakeTimeZoneDetectorStrategy.simulateConfigurationChangeForTests();
-
-        assertTrue(changeCalled[0]);
-        assertTrue(changeCalled[1]);
-    }
-
     private static GeolocationTimeZoneSuggestion createGeolocationTimeZoneSuggestion() {
         return GeolocationTimeZoneSuggestion.createCertainSuggestion(
                 ARBITRARY_ELAPSED_REALTIME_MILLIS, ARBITRARY_ZONE_IDS);
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
index 773abf8..193b2e3 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorServiceTest.java
@@ -60,12 +60,13 @@
     private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 1234L;
 
     private Context mMockContext;
-    private FakeTimeZoneDetectorStrategy mFakeTimeZoneDetectorStrategy;
 
     private TimeZoneDetectorService mTimeZoneDetectorService;
     private HandlerThread mHandlerThread;
     private TestHandler mTestHandler;
     private TestCallerIdentityInjector mTestCallerIdentityInjector;
+    private FakeServiceConfigAccessor mFakeServiceConfigAccessor;
+    private FakeTimeZoneDetectorStrategy mFakeTimeZoneDetectorStrategy;
 
 
     @Before
@@ -81,10 +82,11 @@
         mTestCallerIdentityInjector.initializeCallingUserId(ARBITRARY_USER_ID);
 
         mFakeTimeZoneDetectorStrategy = new FakeTimeZoneDetectorStrategy();
+        mFakeServiceConfigAccessor = new FakeServiceConfigAccessor();
 
         mTimeZoneDetectorService = new TimeZoneDetectorService(
                 mMockContext, mTestHandler, mTestCallerIdentityInjector,
-                mFakeTimeZoneDetectorStrategy);
+                mFakeServiceConfigAccessor, mFakeTimeZoneDetectorStrategy);
     }
 
     @After
@@ -114,7 +116,7 @@
 
         ConfigurationInternal configuration =
                 createConfigurationInternal(true /* autoDetectionEnabled*/);
-        mFakeTimeZoneDetectorStrategy.initializeConfiguration(configuration);
+        mFakeServiceConfigAccessor.initializeConfiguration(configuration);
 
         assertEquals(configuration.createCapabilitiesAndConfig(),
                 mTimeZoneDetectorService.getCapabilitiesAndConfig());
@@ -160,7 +162,7 @@
     public void testListenerRegistrationAndCallbacks() throws Exception {
         ConfigurationInternal initialConfiguration =
                 createConfigurationInternal(false /* autoDetectionEnabled */);
-        mFakeTimeZoneDetectorStrategy.initializeConfiguration(initialConfiguration);
+        mFakeServiceConfigAccessor.initializeConfiguration(initialConfiguration);
 
         IBinder mockListenerBinder = mock(IBinder.class);
         ITimeZoneDetectorListener mockListener = mock(ITimeZoneDetectorListener.class);
@@ -188,6 +190,9 @@
                     createTimeZoneConfiguration(true /* autoDetectionEnabled */);
             mTimeZoneDetectorService.updateConfiguration(autoDetectEnabledConfiguration);
 
+            // The configuration update notification is asynchronous.
+            mTestHandler.waitForMessagesToBeProcessed();
+
             verify(mMockContext).enforceCallingPermission(
                     eq(android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION),
                     anyString());
@@ -349,11 +354,15 @@
         when(mMockContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP))
                 .thenReturn(PackageManager.PERMISSION_GRANTED);
 
+        Dumpable dumpable = mock(Dumpable.class);
+        mTimeZoneDetectorService.addDumpable(dumpable);
+
         PrintWriter pw = new PrintWriter(new StringWriter());
         mTimeZoneDetectorService.dump(null, pw, null);
 
         verify(mMockContext).checkCallingOrSelfPermission(eq(android.Manifest.permission.DUMP));
         mFakeTimeZoneDetectorStrategy.verifyDumpCalled();
+        verify(dumpable).dump(any(), any());
     }
 
     private static TimeZoneConfiguration createTimeZoneConfiguration(boolean autoDetectionEnabled) {
@@ -363,16 +372,17 @@
     }
 
     private static ConfigurationInternal createConfigurationInternal(boolean autoDetectionEnabled) {
-        // Default geo detection settings from auto detection settings - they are not important to
-        // the tests.
+        // Default geo detection settings from the auto detection setting - they are not important
+        // to the tests.
         final boolean geoDetectionEnabled = autoDetectionEnabled;
         return new ConfigurationInternal.Builder(ARBITRARY_USER_ID)
                 .setTelephonyDetectionFeatureSupported(true)
                 .setGeoDetectionFeatureSupported(true)
+                .setTelephonyFallbackSupported(false)
                 .setUserConfigAllowed(true)
-                .setAutoDetectionEnabled(autoDetectionEnabled)
-                .setLocationEnabled(geoDetectionEnabled)
-                .setGeoDetectionEnabled(geoDetectionEnabled)
+                .setAutoDetectionEnabledSetting(autoDetectionEnabled)
+                .setLocationEnabledSetting(geoDetectionEnabled)
+                .setGeoDetectionEnabledSetting(geoDetectionEnabled)
                 .build();
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
index e2e8755..ef1b4f5 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/TimeZoneDetectorStrategyImplTest.java
@@ -32,33 +32,26 @@
 import static com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.TELEPHONY_SCORE_USAGE_THRESHOLD;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
 import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.UserIdInt;
-import android.app.time.TimeZoneConfiguration;
 import android.app.timezonedetector.ManualTimeZoneSuggestion;
 import android.app.timezonedetector.TelephonyTimeZoneSuggestion;
 import android.app.timezonedetector.TelephonyTimeZoneSuggestion.MatchType;
 import android.app.timezonedetector.TelephonyTimeZoneSuggestion.Quality;
-import android.util.IndentingPrintWriter;
 
 import com.android.server.timezonedetector.TimeZoneDetectorStrategyImpl.QualifiedTelephonyTimeZoneSuggestion;
 
 import org.junit.Before;
 import org.junit.Test;
 
-import java.io.StringWriter;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Function;
 
 /**
@@ -66,8 +59,9 @@
  */
 public class TimeZoneDetectorStrategyImplTest {
 
-    /** A time zone used for initialization that does not occur elsewhere in tests. */
     private static final @UserIdInt int USER_ID = 9876;
+    private static final long ARBITRARY_ELAPSED_REALTIME_MILLIS = 1234;
+    /** A time zone used for initialization that does not occur elsewhere in tests. */
     private static final String ARBITRARY_TIME_ZONE_ID = "Etc/UTC";
     private static final int SLOT_INDEX1 = 10000;
     private static final int SLOT_INDEX2 = 20000;
@@ -91,221 +85,80 @@
                     TELEPHONY_SCORE_HIGHEST),
     };
 
-    private static final ConfigurationInternal CONFIG_INT_USER_RESTRICTED_AUTO_DISABLED =
+    private static final ConfigurationInternal CONFIG_USER_RESTRICTED_AUTO_DISABLED =
             new ConfigurationInternal.Builder(USER_ID)
                     .setUserConfigAllowed(false)
                     .setTelephonyDetectionFeatureSupported(true)
                     .setGeoDetectionFeatureSupported(true)
-                    .setAutoDetectionEnabled(false)
-                    .setLocationEnabled(true)
-                    .setGeoDetectionEnabled(false)
+                    .setTelephonyFallbackSupported(false)
+                    .setAutoDetectionEnabledSetting(false)
+                    .setLocationEnabledSetting(true)
+                    .setGeoDetectionEnabledSetting(false)
                     .build();
 
-    private static final ConfigurationInternal CONFIG_INT_USER_RESTRICTED_AUTO_ENABLED =
+    private static final ConfigurationInternal CONFIG_USER_RESTRICTED_AUTO_ENABLED =
             new ConfigurationInternal.Builder(USER_ID)
                     .setUserConfigAllowed(false)
                     .setTelephonyDetectionFeatureSupported(true)
                     .setGeoDetectionFeatureSupported(true)
-                    .setAutoDetectionEnabled(true)
-                    .setLocationEnabled(true)
-                    .setGeoDetectionEnabled(true)
+                    .setTelephonyFallbackSupported(false)
+                    .setAutoDetectionEnabledSetting(true)
+                    .setLocationEnabledSetting(true)
+                    .setGeoDetectionEnabledSetting(true)
                     .build();
 
-    private static final ConfigurationInternal CONFIG_INT_AUTO_DETECT_NOT_SUPPORTED =
+    private static final ConfigurationInternal CONFIG_AUTO_DETECT_NOT_SUPPORTED =
             new ConfigurationInternal.Builder(USER_ID)
                     .setUserConfigAllowed(true)
                     .setTelephonyDetectionFeatureSupported(false)
                     .setGeoDetectionFeatureSupported(false)
-                    .setAutoDetectionEnabled(false)
-                    .setLocationEnabled(true)
-                    .setGeoDetectionEnabled(false)
+                    .setTelephonyFallbackSupported(false)
+                    .setAutoDetectionEnabledSetting(false)
+                    .setLocationEnabledSetting(true)
+                    .setGeoDetectionEnabledSetting(false)
                     .build();
 
-    private static final ConfigurationInternal CONFIG_INT_TELEPHONY_SUPPORTED_GEO_NOT_SUPPORTED =
-            new ConfigurationInternal.Builder(USER_ID)
-                    .setUserConfigAllowed(true)
-                    .setTelephonyDetectionFeatureSupported(true)
-                    .setGeoDetectionFeatureSupported(false)
-                    .setAutoDetectionEnabled(true)
-                    .setLocationEnabled(true)
-                    .setGeoDetectionEnabled(true)
-                    .build();
-
-    private static final ConfigurationInternal CONFIG_INT_AUTO_DISABLED_GEO_DISABLED =
+    private static final ConfigurationInternal CONFIG_AUTO_DISABLED_GEO_DISABLED =
             new ConfigurationInternal.Builder(USER_ID)
                     .setUserConfigAllowed(true)
                     .setTelephonyDetectionFeatureSupported(true)
                     .setGeoDetectionFeatureSupported(true)
-                    .setAutoDetectionEnabled(false)
-                    .setLocationEnabled(true)
-                    .setGeoDetectionEnabled(false)
+                    .setTelephonyFallbackSupported(false)
+                    .setAutoDetectionEnabledSetting(false)
+                    .setLocationEnabledSetting(true)
+                    .setGeoDetectionEnabledSetting(false)
                     .build();
 
-    private static final ConfigurationInternal CONFIG_INT_AUTO_ENABLED_GEO_DISABLED =
+    private static final ConfigurationInternal CONFIG_AUTO_ENABLED_GEO_DISABLED =
             new ConfigurationInternal.Builder(USER_ID)
                     .setTelephonyDetectionFeatureSupported(true)
                     .setGeoDetectionFeatureSupported(true)
+                    .setTelephonyFallbackSupported(false)
                     .setUserConfigAllowed(true)
-                    .setAutoDetectionEnabled(true)
-                    .setLocationEnabled(true)
-                    .setGeoDetectionEnabled(false)
+                    .setAutoDetectionEnabledSetting(true)
+                    .setLocationEnabledSetting(true)
+                    .setGeoDetectionEnabledSetting(false)
                     .build();
 
-    private static final ConfigurationInternal CONFIG_INT_AUTO_ENABLED_GEO_ENABLED =
+    private static final ConfigurationInternal CONFIG_AUTO_ENABLED_GEO_ENABLED =
             new ConfigurationInternal.Builder(USER_ID)
                     .setTelephonyDetectionFeatureSupported(true)
                     .setGeoDetectionFeatureSupported(true)
+                    .setTelephonyFallbackSupported(false)
                     .setUserConfigAllowed(true)
-                    .setAutoDetectionEnabled(true)
-                    .setLocationEnabled(true)
-                    .setGeoDetectionEnabled(true)
+                    .setAutoDetectionEnabledSetting(true)
+                    .setLocationEnabledSetting(true)
+                    .setGeoDetectionEnabledSetting(true)
                     .build();
 
-    private static final TimeZoneConfiguration CONFIG_AUTO_DISABLED =
-            createConfig(false /* autoDetection */, null);
-    private static final TimeZoneConfiguration CONFIG_AUTO_ENABLED =
-            createConfig(true /* autoDetection */, null);
-    private static final TimeZoneConfiguration CONFIG_GEO_DETECTION_ENABLED =
-            createConfig(null, true /* geoDetection */);
-    private static final TimeZoneConfiguration CONFIG_GEO_DETECTION_DISABLED =
-            createConfig(null, false /* geoDetection */);
-
     private TimeZoneDetectorStrategyImpl mTimeZoneDetectorStrategy;
     private FakeEnvironment mFakeEnvironment;
-    private MockConfigChangeListener mMockConfigChangeListener;
-
-    // A fake source of time for suggestions. This will typically be incremented after every use.
-    @ElapsedRealtimeLong private long mElapsedRealtimeMillis;
 
     @Before
     public void setUp() {
         mFakeEnvironment = new FakeEnvironment();
-        mMockConfigChangeListener = new MockConfigChangeListener();
+        mFakeEnvironment.initializeConfig(CONFIG_AUTO_DISABLED_GEO_DISABLED);
         mTimeZoneDetectorStrategy = new TimeZoneDetectorStrategyImpl(mFakeEnvironment);
-        mTimeZoneDetectorStrategy.addConfigChangeListener(mMockConfigChangeListener);
-    }
-
-    @Test
-    public void testGetCurrentUserConfiguration() {
-        new Script().initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED);
-        ConfigurationInternal expectedConfiguration =
-                mFakeEnvironment.getConfigurationInternal(USER_ID);
-        assertEquals(expectedConfiguration,
-                mTimeZoneDetectorStrategy.getCurrentUserConfigurationInternal());
-    }
-
-    @Test
-    public void testUpdateConfiguration_unrestricted() {
-        Script script = new Script().initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED);
-
-        // Set the configuration with auto detection enabled.
-        script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */);
-
-        // Nothing should have happened: it was initialized in this state.
-        script.verifyConfigurationNotChanged();
-
-        // Update the configuration with auto detection disabled.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */);
-
-        // The settings should have been changed and the StrategyListener onChange() called.
-        script.verifyConfigurationChangedAndReset(CONFIG_INT_AUTO_DISABLED_GEO_DISABLED);
-
-        // Update the configuration with auto detection enabled.
-        script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */);
-
-        // The settings should have been changed and the StrategyListener onChange() called.
-        script.verifyConfigurationChangedAndReset(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED);
-
-        // Update the configuration to enable geolocation time zone detection.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_GEO_DETECTION_ENABLED,  true /* expectedResult */);
-
-        // The settings should have been changed and the StrategyListener onChange() called.
-        script.verifyConfigurationChangedAndReset(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED);
-    }
-
-    @Test
-    public void testUpdateConfiguration_restricted() {
-        Script script = new Script().initializeConfig(CONFIG_INT_USER_RESTRICTED_AUTO_ENABLED);
-
-        // Try to update the configuration with auto detection disabled.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_AUTO_DISABLED, false /* expectedResult */);
-
-        // The settings should not have been changed: user shouldn't have the capabilities.
-        script.verifyConfigurationNotChanged();
-
-        // Try to update the configuration with auto detection enabled.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_AUTO_ENABLED,  false /* expectedResult */);
-
-        // The settings should not have been changed: user shouldn't have the capabilities.
-        script.verifyConfigurationNotChanged();
-
-        // Try to update the configuration to enable geolocation time zone detection: this should
-        // succeed, the geolocation time zone detection setting is not covered by the restriction).
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_GEO_DETECTION_DISABLED,  true /* expectedResult */);
-
-        // The settings should have been changed.
-        ConfigurationInternal expectedConfig = new ConfigurationInternal.Builder(
-                CONFIG_INT_USER_RESTRICTED_AUTO_ENABLED)
-                .setGeoDetectionEnabled(false)
-                .build();
-        script.verifyConfigurationChangedAndReset(expectedConfig);
-    }
-
-    @Test
-    public void testUpdateConfiguration_autoDetectNotSupported() {
-        Script script = new Script().initializeConfig(CONFIG_INT_AUTO_DETECT_NOT_SUPPORTED);
-
-        // Try to update the configuration with auto detection disabled.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_AUTO_DISABLED, false /* expectedResult */);
-
-        // The settings should not have been changed: user shouldn't have the capabilities.
-        script.verifyConfigurationNotChanged();
-
-        // Try to update the configuration with auto detection enabled.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_AUTO_ENABLED, false /* expectedResult */);
-
-        // The settings should not have been changed: user shouldn't have the capabilities.
-        script.verifyConfigurationNotChanged();
-    }
-
-    @Test
-    public void testUpdateConfiguration_autoDetectSupportedGeoNotSupported() {
-        Script script = new Script().initializeConfig(
-                CONFIG_INT_TELEPHONY_SUPPORTED_GEO_NOT_SUPPORTED);
-
-        // Update the configuration with auto detection disabled.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */);
-
-        // The settings should have been changed and the StrategyListener onChange() called.
-        ConfigurationInternal expectedConfig =
-                new ConfigurationInternal.Builder(CONFIG_INT_TELEPHONY_SUPPORTED_GEO_NOT_SUPPORTED)
-                        .setAutoDetectionEnabled(false)
-                        .build();
-        script.verifyConfigurationChangedAndReset(expectedConfig);
-
-        // Try to update the configuration with geo detection disabled.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_GEO_DETECTION_DISABLED, false /* expectedResult */);
-
-        // The settings should not have been changed: user shouldn't have the capability to modify
-        // the setting when the feature is disabled.
-        script.verifyConfigurationNotChanged();
-
-        // Try to update the configuration with geo detection enabled.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_GEO_DETECTION_ENABLED, false /* expectedResult */);
-
-        // The settings should not have been changed: user shouldn't have the capability to modify
-        // the setting when the feature is disabled.
-        script.verifyConfigurationNotChanged();
     }
 
     @Test
@@ -315,8 +168,9 @@
         TelephonyTimeZoneSuggestion slotIndex2TimeZoneSuggestion =
                 createEmptySlotIndex2Suggestion();
         Script script = new Script()
-                .initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED_GEO_DISABLED)
+                .resetConfigurationTracking();
 
         script.simulateTelephonyTimeZoneSuggestion(slotIndex1TimeZoneSuggestion)
                 .verifyTimeZoneNotChanged();
@@ -360,7 +214,9 @@
         TelephonyTestCase testCase2 = newTelephonyTestCase(MATCH_TYPE_NETWORK_COUNTRY_ONLY,
                 QUALITY_SINGLE_ZONE, TELEPHONY_SCORE_HIGH);
 
-        Script script = new Script().initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED);
+        Script script = new Script()
+                .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED_GEO_DISABLED)
+                .resetConfigurationTracking();
 
         // A low quality suggestions will not be taken: The device time zone setting is left
         // uninitialized.
@@ -425,8 +281,9 @@
 
         for (TelephonyTestCase testCase : TELEPHONY_TEST_CASES) {
             // Start with the device in a known state.
-            script.initializeConfig(CONFIG_INT_AUTO_DISABLED_GEO_DISABLED)
-                    .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+            script.initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                    .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED_GEO_DISABLED)
+                    .resetConfigurationTracking();
 
             TelephonyTimeZoneSuggestion suggestion =
                     testCase.createSuggestion(SLOT_INDEX1, "Europe/London");
@@ -445,8 +302,7 @@
                     mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
 
             // Toggling the time zone setting on should cause the device setting to be set.
-            script.simulateUpdateConfiguration(
-                    USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */);
+            script.simulateSetAutoMode(true);
 
             // When time zone detection is already enabled the suggestion (if it scores highly
             // enough) should be set immediately.
@@ -463,8 +319,7 @@
                     mTimeZoneDetectorStrategy.findBestTelephonySuggestionForTests());
 
             // Toggling the time zone setting should off should do nothing.
-            script.simulateUpdateConfiguration(
-                    USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
+            script.simulateSetAutoMode(false)
                     .verifyTimeZoneNotChanged();
 
             // Assert internal service state.
@@ -478,8 +333,9 @@
     @Test
     public void testTelephonySuggestionsSingleSlotId() {
         Script script = new Script()
-                .initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED_GEO_DISABLED)
+                .resetConfigurationTracking();
 
         for (TelephonyTestCase testCase : TELEPHONY_TEST_CASES) {
             makeSlotIndex1SuggestionAndCheckState(script, testCase);
@@ -543,8 +399,10 @@
                         TELEPHONY_SCORE_NONE);
 
         Script script = new Script()
-                .initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED)
                 .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED_GEO_DISABLED)
+                .resetConfigurationTracking()
+
                 // Initialize the latest suggestions as empty so we don't need to worry about nulls
                 // below for the first loop.
                 .simulateTelephonyTimeZoneSuggestion(emptySlotIndex1Suggestion)
@@ -628,7 +486,9 @@
      */
     @Test
     public void testTelephonySuggestionStrategyDoesNotAssumeCurrentSetting_autoTelephony() {
-        Script script = new Script().initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED);
+        Script script = new Script()
+                .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED_GEO_DISABLED)
+                .resetConfigurationTracking();
 
         TelephonyTestCase testCase = newTelephonyTestCase(
                 MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE, TELEPHONY_SCORE_HIGH);
@@ -646,20 +506,18 @@
 
         // Toggling time zone detection should set the device time zone only if the current setting
         // value is different from the most recent telephony suggestion.
-        script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
+        script.simulateSetAutoMode(false)
                 .verifyTimeZoneNotChanged()
-                .simulateUpdateConfiguration(
-                        USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
+                .simulateSetAutoMode(true)
                 .verifyTimeZoneNotChanged();
 
         // Simulate a user turning auto detection off, a new suggestion being made while auto
         // detection is off, and the user turning it on again.
-        script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_DISABLED, true /* expectedResult */)
+        script.simulateSetAutoMode(false)
                 .simulateTelephonyTimeZoneSuggestion(newYorkSuggestion)
                 .verifyTimeZoneNotChanged();
         // Latest suggestion should be used.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
+        script.simulateSetAutoMode(true)
                 .verifyTimeZoneChangedAndReset(newYorkSuggestion);
     }
 
@@ -676,12 +534,13 @@
     private void checkManualSuggestion_unrestricted_autoDetectionEnabled(
             boolean geoDetectionEnabled) {
         ConfigurationInternal geoTzEnabledConfig =
-                new ConfigurationInternal.Builder(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED)
-                        .setGeoDetectionEnabled(geoDetectionEnabled)
+                new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED_GEO_DISABLED)
+                        .setGeoDetectionEnabledSetting(geoDetectionEnabled)
                         .build();
         Script script = new Script()
-                .initializeConfig(geoTzEnabledConfig)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(geoTzEnabledConfig)
+                .resetConfigurationTracking();
 
         // Auto time zone detection is enabled so the manual suggestion should be ignored.
         script.simulateManualTimeZoneSuggestion(
@@ -694,8 +553,9 @@
     @Test
     public void testManualSuggestion_restricted_simulateAutoTimeZoneEnabled() {
         Script script = new Script()
-                .initializeConfig(CONFIG_INT_USER_RESTRICTED_AUTO_ENABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_USER_RESTRICTED_AUTO_ENABLED)
+                .resetConfigurationTracking();
 
         // User is restricted so the manual suggestion should be ignored.
         script.simulateManualTimeZoneSuggestion(
@@ -708,8 +568,9 @@
     @Test
     public void testManualSuggestion_unrestricted_autoTimeZoneDetectionDisabled() {
         Script script = new Script()
-                .initializeConfig(CONFIG_INT_AUTO_DISABLED_GEO_DISABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED_GEO_DISABLED)
+                .resetConfigurationTracking();
 
         // Auto time zone detection is disabled so the manual suggestion should be used.
         ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Europe/Paris");
@@ -723,8 +584,9 @@
     @Test
     public void testManualSuggestion_restricted_autoTimeZoneDetectionDisabled() {
         Script script = new Script()
-                .initializeConfig(CONFIG_INT_USER_RESTRICTED_AUTO_DISABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_USER_RESTRICTED_AUTO_DISABLED)
+                .resetConfigurationTracking();
 
         // Restricted users do not have the capability.
         ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Europe/Paris");
@@ -738,8 +600,9 @@
     @Test
     public void testManualSuggestion_autoDetectNotSupported() {
         Script script = new Script()
-                .initializeConfig(CONFIG_INT_AUTO_DETECT_NOT_SUPPORTED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_AUTO_DETECT_NOT_SUPPORTED)
+                .resetConfigurationTracking();
 
         // Unrestricted users have the capability.
         ManualTimeZoneSuggestion manualSuggestion = createManualSuggestion("Europe/Paris");
@@ -752,8 +615,10 @@
 
     @Test
     public void testGeoSuggestion_uncertain() {
-        Script script = new Script().initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+        Script script = new Script()
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED_GEO_ENABLED)
+                .resetConfigurationTracking();
 
         GeolocationTimeZoneSuggestion uncertainSuggestion = createUncertainGeolocationSuggestion();
 
@@ -768,8 +633,9 @@
     @Test
     public void testGeoSuggestion_noZones() {
         Script script = new Script()
-                .initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED_GEO_ENABLED)
+                .resetConfigurationTracking();
 
         GeolocationTimeZoneSuggestion noZonesSuggestion = createCertainGeolocationSuggestion();
 
@@ -786,11 +652,12 @@
                 createCertainGeolocationSuggestion("Europe/London");
 
         Script script = new Script()
-                .initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED_GEO_ENABLED)
+                .resetConfigurationTracking();
 
         script.simulateGeolocationTimeZoneSuggestion(suggestion)
-                .verifyTimeZoneChangedAndReset("Europe/London");
+                .verifyTimeZoneChangedAndReset(suggestion);
 
         // Assert internal service state.
         assertEquals(suggestion, mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
@@ -811,11 +678,12 @@
                 createCertainGeolocationSuggestion("Europe/Paris");
 
         Script script = new Script()
-                .initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED_GEO_ENABLED)
+                .resetConfigurationTracking();
 
         script.simulateGeolocationTimeZoneSuggestion(londonOnlySuggestion)
-                .verifyTimeZoneChangedAndReset("Europe/London");
+                .verifyTimeZoneChangedAndReset(londonOnlySuggestion);
         assertEquals(londonOnlySuggestion,
                 mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
 
@@ -826,7 +694,7 @@
                 mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
 
         script.simulateGeolocationTimeZoneSuggestion(parisOnlySuggestion)
-                .verifyTimeZoneChangedAndReset("Europe/Paris");
+                .verifyTimeZoneChangedAndReset(parisOnlySuggestion);
         assertEquals(parisOnlySuggestion,
                 mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
 
@@ -838,29 +706,6 @@
                 mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
     }
 
-    @Test
-    public void testGeoSuggestion_togglingGeoDetectionClearsLastSuggestion() {
-        GeolocationTimeZoneSuggestion suggestion =
-                createCertainGeolocationSuggestion("Europe/London");
-
-        Script script = new Script()
-                .initializeConfig(CONFIG_INT_AUTO_ENABLED_GEO_ENABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
-
-        script.simulateGeolocationTimeZoneSuggestion(suggestion)
-                .verifyTimeZoneChangedAndReset("Europe/London");
-
-        // Assert internal service state.
-        assertEquals(suggestion, mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
-
-        // Turn off geo detection and verify the latest suggestion is cleared.
-        script.simulateUpdateConfiguration(USER_ID, CONFIG_GEO_DETECTION_DISABLED, true)
-                .verifyConfigurationChangedAndReset(CONFIG_INT_AUTO_ENABLED_GEO_DISABLED);
-
-        // Assert internal service state.
-        assertNull(mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
-    }
-
     /**
      * Confirms that changing the geolocation time zone detection enabled setting has the expected
      * behavior, i.e. immediately recompute the detected time zone using different signals.
@@ -874,76 +719,250 @@
                 "Europe/Paris");
 
         Script script = new Script()
-                .initializeConfig(CONFIG_INT_AUTO_DISABLED_GEO_DISABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED_GEO_DISABLED)
+                .resetConfigurationTracking();
 
         // Add suggestions. Nothing should happen as time zone detection is disabled.
         script.simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
                 .verifyTimeZoneNotChanged();
 
-        // Geolocation suggestions are only stored when geolocation detection is enabled.
-        assertNull(mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+        assertEquals(geolocationSuggestion,
+                mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
 
         script.simulateTelephonyTimeZoneSuggestion(telephonySuggestion)
                 .verifyTimeZoneNotChanged();
 
-        // Telephony suggestions are always stored.
         assertEquals(telephonySuggestion,
                 mTimeZoneDetectorStrategy.getLatestTelephonySuggestion(SLOT_INDEX1).suggestion);
 
         // Toggling the time zone detection enabled setting on should cause the device setting to be
         // set from the telephony signal, as we've started with geolocation time zone detection
         // disabled.
-        script.simulateUpdateConfiguration(USER_ID, CONFIG_AUTO_ENABLED, true /* expectedResult */)
+        script.simulateSetAutoMode(true)
                 .verifyTimeZoneChangedAndReset(telephonySuggestion);
 
-        // Changing the detection to enable geo detection won't cause the device tz setting to
-        // change because the geo suggestion is empty.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_GEO_DETECTION_ENABLED, true /* expectedResult */)
-                .verifyTimeZoneNotChanged()
-                .simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
-                .verifyTimeZoneChangedAndReset(geolocationSuggestion.getZoneIds().get(0));
+        // Changing the detection to enable geo detection will cause the device tz setting to
+        // change to use the latest geolocation suggestion.
+        script.simulateSetGeoDetectionEnabled(true)
+                .verifyTimeZoneChangedAndReset(geolocationSuggestion);
 
         // Changing the detection to disable geo detection should cause the device tz setting to
         // change to the telephony suggestion.
-        script.simulateUpdateConfiguration(
-                USER_ID, CONFIG_GEO_DETECTION_DISABLED, true /* expectedResult */)
+        script.simulateSetGeoDetectionEnabled(false)
                 .verifyTimeZoneChangedAndReset(telephonySuggestion);
 
-        assertNull(mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
+        assertEquals(geolocationSuggestion,
+                mTimeZoneDetectorStrategy.getLatestGeolocationSuggestion());
     }
 
     @Test
-    public void testAddDumpable() {
-        new Script()
-                .initializeConfig(CONFIG_INT_AUTO_DISABLED_GEO_DISABLED)
-                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID);
+    public void testTelephonyFallback() {
+        ConfigurationInternal config = new ConfigurationInternal.Builder(
+                CONFIG_AUTO_ENABLED_GEO_ENABLED)
+                .setTelephonyFallbackSupported(true)
+                .build();
 
-        AtomicBoolean dumpCalled = new AtomicBoolean(false);
-        class FakeDumpable implements Dumpable {
-            @Override
-            public void dump(IndentingPrintWriter pw, String[] args) {
-                dumpCalled.set(true);
-            }
+        Script script = new Script()
+                .initializeClock(ARBITRARY_ELAPSED_REALTIME_MILLIS)
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(config)
+                .resetConfigurationTracking();
+
+        // Confirm initial state is as expected.
+        script.verifyTelephonyFallbackIsEnabled(true)
+                .verifyTimeZoneNotChanged();
+
+        // Although geolocation detection is enabled, telephony fallback should be used initially
+        // and until a suitable "certain" geolocation suggestion is received.
+        {
+            TelephonyTimeZoneSuggestion telephonySuggestion = createTelephonySuggestion(
+                    SLOT_INDEX1, MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE,
+                    "Europe/Paris");
+            script.simulateIncrementClock()
+                    .simulateTelephonyTimeZoneSuggestion(telephonySuggestion)
+                    .verifyTimeZoneChangedAndReset(telephonySuggestion)
+                    .verifyTelephonyFallbackIsEnabled(true);
         }
 
-        mTimeZoneDetectorStrategy.addDumpable(new FakeDumpable());
-        IndentingPrintWriter ipw = new IndentingPrintWriter(new StringWriter());
-        String[] args = {"ArgOne", "ArgTwo"};
-        mTimeZoneDetectorStrategy.dump(ipw, args);
+        // Receiving an "uncertain" geolocation suggestion should have no effect.
+        {
+            GeolocationTimeZoneSuggestion uncertainGeolocationSuggestion =
+                    createUncertainGeolocationSuggestion();
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(uncertainGeolocationSuggestion)
+                    .verifyTimeZoneNotChanged()
+                    .verifyTelephonyFallbackIsEnabled(true);
+        }
 
-        assertTrue(dumpCalled.get());
+        // Receiving a "certain" geolocation suggestion should disable telephony fallback mode.
+        {
+            GeolocationTimeZoneSuggestion geolocationSuggestion =
+                    createCertainGeolocationSuggestion("Europe/London");
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
+                    .verifyTimeZoneChangedAndReset(geolocationSuggestion)
+                    .verifyTelephonyFallbackIsEnabled(false);
+        }
+
+        // Used to record the last telephony suggestion received, which will be used when fallback
+        // takes place.
+        TelephonyTimeZoneSuggestion lastTelephonySuggestion;
+
+        // Telephony suggestions should now be ignored and geolocation detection is "in control".
+        {
+            TelephonyTimeZoneSuggestion telephonySuggestion = createTelephonySuggestion(
+                    SLOT_INDEX1, MATCH_TYPE_NETWORK_COUNTRY_AND_OFFSET, QUALITY_SINGLE_ZONE,
+                    "Europe/Berlin");
+            script.simulateIncrementClock()
+                    .simulateTelephonyTimeZoneSuggestion(telephonySuggestion)
+                    .verifyTimeZoneNotChanged()
+                    .verifyTelephonyFallbackIsEnabled(false);
+            lastTelephonySuggestion = telephonySuggestion;
+        }
+
+        // Geolocation suggestions should continue to be used as normal (previous telephony
+        // suggestions are not used, even when the geolocation suggestion is uncertain).
+        {
+            GeolocationTimeZoneSuggestion geolocationSuggestion =
+                    createCertainGeolocationSuggestion("Europe/Rome");
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
+                    .verifyTimeZoneChangedAndReset(geolocationSuggestion)
+                    .verifyTelephonyFallbackIsEnabled(false);
+
+            GeolocationTimeZoneSuggestion uncertainGeolocationSuggestion =
+                    createUncertainGeolocationSuggestion();
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(uncertainGeolocationSuggestion)
+                    .verifyTimeZoneNotChanged()
+                    .verifyTelephonyFallbackIsEnabled(false);
+
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
+                    // No change needed, device will already be set to Europe/Rome.
+                    .verifyTimeZoneNotChanged()
+                    .verifyTelephonyFallbackIsEnabled(false);
+        }
+
+        // Enable telephony fallback. Nothing will change, because the geolocation is still certain,
+        // but fallback will remain enabled.
+        {
+            script.simulateIncrementClock()
+                    .simulateEnableTelephonyFallback()
+                    .verifyTimeZoneNotChanged()
+                    .verifyTelephonyFallbackIsEnabled(true);
+        }
+
+        // Make the geolocation algorithm uncertain.
+        {
+            GeolocationTimeZoneSuggestion uncertainGeolocationSuggestion =
+                    createUncertainGeolocationSuggestion();
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(uncertainGeolocationSuggestion)
+                    .verifyTimeZoneChangedAndReset(lastTelephonySuggestion)
+                    .verifyTelephonyFallbackIsEnabled(true);
+        }
+
+        // Make the geolocation algorithm certain, disabling telephony fallback.
+        {
+            GeolocationTimeZoneSuggestion geolocationSuggestion =
+                    createCertainGeolocationSuggestion("Europe/Lisbon");
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
+                    .verifyTimeZoneChangedAndReset(geolocationSuggestion)
+                    .verifyTelephonyFallbackIsEnabled(false);
+
+        }
+
+        // Demonstrate what happens when geolocation is uncertain when telephony fallback is
+        // enabled.
+        {
+            GeolocationTimeZoneSuggestion uncertainGeolocationSuggestion =
+                    createUncertainGeolocationSuggestion();
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(uncertainGeolocationSuggestion)
+                    .verifyTimeZoneNotChanged()
+                    .verifyTelephonyFallbackIsEnabled(false)
+                    .simulateEnableTelephonyFallback()
+                    .verifyTimeZoneChangedAndReset(lastTelephonySuggestion)
+                    .verifyTelephonyFallbackIsEnabled(true);
+        }
+    }
+
+    @Test
+    public void testTelephonyFallback_noTelephonySuggestionToFallBackTo() {
+        ConfigurationInternal config = new ConfigurationInternal.Builder(
+                CONFIG_AUTO_ENABLED_GEO_ENABLED)
+                .setTelephonyFallbackSupported(true)
+                .build();
+
+        Script script = new Script()
+                .initializeClock(ARBITRARY_ELAPSED_REALTIME_MILLIS)
+                .initializeTimeZoneSetting(ARBITRARY_TIME_ZONE_ID)
+                .simulateConfigurationInternalChange(config)
+                .resetConfigurationTracking();
+
+        // Confirm initial state is as expected.
+        script.verifyTelephonyFallbackIsEnabled(true)
+                .verifyTimeZoneNotChanged();
+
+        // Receiving an "uncertain" geolocation suggestion should have no effect.
+        {
+            GeolocationTimeZoneSuggestion uncertainGeolocationSuggestion =
+                    createUncertainGeolocationSuggestion();
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(uncertainGeolocationSuggestion)
+                    .verifyTimeZoneNotChanged()
+                    .verifyTelephonyFallbackIsEnabled(true);
+        }
+
+        // Make an uncertain geolocation suggestion, there is no telephony suggestion to fall back
+        // to
+        {
+            GeolocationTimeZoneSuggestion uncertainGeolocationSuggestion =
+                    createUncertainGeolocationSuggestion();
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(uncertainGeolocationSuggestion)
+                    .verifyTimeZoneNotChanged()
+                    .verifyTelephonyFallbackIsEnabled(true);
+        }
+
+        // Similar to the case above, but force a fallback attempt after making a "certain"
+        // geolocation suggestion.
+        // Geolocation suggestions should continue to be used as normal (previous telephony
+        // suggestions are not used, even when the geolocation suggestion is uncertain).
+        {
+            GeolocationTimeZoneSuggestion geolocationSuggestion =
+                    createCertainGeolocationSuggestion("Europe/Rome");
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(geolocationSuggestion)
+                    .verifyTimeZoneChangedAndReset(geolocationSuggestion)
+                    .verifyTelephonyFallbackIsEnabled(false);
+
+            GeolocationTimeZoneSuggestion uncertainGeolocationSuggestion =
+                    createUncertainGeolocationSuggestion();
+            script.simulateIncrementClock()
+                    .simulateGeolocationTimeZoneSuggestion(uncertainGeolocationSuggestion)
+                    .verifyTimeZoneNotChanged()
+                    .verifyTelephonyFallbackIsEnabled(false);
+
+            script.simulateIncrementClock()
+                    .simulateEnableTelephonyFallback()
+                    .verifyTimeZoneNotChanged()
+                    .verifyTelephonyFallbackIsEnabled(true);
+        }
     }
 
     @Test
     public void testGenerateMetricsState() {
-        ConfigurationInternal expectedInternalConfig = CONFIG_INT_AUTO_DISABLED_GEO_DISABLED;
+        ConfigurationInternal expectedInternalConfig = CONFIG_AUTO_DISABLED_GEO_DISABLED;
         String expectedDeviceTimeZoneId = "InitialZoneId";
 
         Script script = new Script()
-                .initializeConfig(expectedInternalConfig)
-                .initializeTimeZoneSetting(expectedDeviceTimeZoneId);
+                .initializeTimeZoneSetting(expectedDeviceTimeZoneId)
+                .simulateConfigurationInternalChange(expectedInternalConfig)
+                .resetConfigurationTracking();
 
         assertMetricsState(expectedInternalConfig, expectedDeviceTimeZoneId, null, null,
                 null, MetricsTimeZoneDetectorState.DETECTION_MODE_MANUAL);
@@ -958,9 +977,7 @@
                 manualSuggestion, null, null,
                 MetricsTimeZoneDetectorState.DETECTION_MODE_MANUAL);
 
-        // With time zone auto detection off, telephony suggestions will be recorded, but geo
-        // suggestions won't out of an abundance of caution around respecting user privacy when
-        // geo detection is off.
+        // With time zone auto detection off, telephony and geo suggestions will be recorded.
         TelephonyTimeZoneSuggestion telephonySuggestion =
                 createTelephonySuggestion(0 /* slotIndex */, MATCH_TYPE_NETWORK_COUNTRY_ONLY,
                         QUALITY_SINGLE_ZONE, "Zone2");
@@ -972,26 +989,17 @@
                 .verifyTimeZoneNotChanged();
 
         assertMetricsState(expectedInternalConfig, expectedDeviceTimeZoneId,
-                manualSuggestion, telephonySuggestion, null /* expectedGeoSuggestion */,
+                manualSuggestion, telephonySuggestion, geolocationTimeZoneSuggestion,
                 MetricsTimeZoneDetectorState.DETECTION_MODE_MANUAL);
 
         // Update the config and confirm that the config metrics state updates also.
-        TimeZoneConfiguration configUpdate =
-                createConfig(true /* autoDetection */, true /* geoDetection */);
         expectedInternalConfig = new ConfigurationInternal.Builder(expectedInternalConfig)
-                .setAutoDetectionEnabled(true)
-                .setGeoDetectionEnabled(true)
+                .setAutoDetectionEnabledSetting(true)
+                .setGeoDetectionEnabledSetting(true)
                 .build();
-        script.simulateUpdateConfiguration(USER_ID, configUpdate, true /* expectedResult */)
-                .verifyConfigurationChangedAndReset(expectedInternalConfig)
-                .verifyTimeZoneNotChanged();
-        assertMetricsState(expectedInternalConfig, expectedDeviceTimeZoneId,
-                manualSuggestion, telephonySuggestion, null  /* expectedGeoSuggestion */,
-                MetricsTimeZoneDetectorState.DETECTION_MODE_GEO);
 
-        // Now simulate a geo suggestion and confirm it is used and reported in the metrics too.
         expectedDeviceTimeZoneId = geolocationTimeZoneSuggestion.getZoneIds().get(0);
-        script.simulateGeolocationTimeZoneSuggestion(geolocationTimeZoneSuggestion)
+        script.simulateConfigurationInternalChange(expectedInternalConfig)
                 .verifyTimeZoneChangedAndReset(expectedDeviceTimeZoneId);
         assertMetricsState(expectedInternalConfig, expectedDeviceTimeZoneId,
                 manualSuggestion, telephonySuggestion, geolocationTimeZoneSuggestion,
@@ -1029,6 +1037,8 @@
         assertEquals(config.isTelephonyDetectionSupported(),
                 actualState.isTelephonyDetectionSupported());
         assertEquals(config.isGeoDetectionSupported(), actualState.isGeoDetectionSupported());
+        assertEquals(config.isTelephonyFallbackSupported(),
+                actualState.isTelephonyTimeZoneFallbackSupported());
         assertEquals(config.getAutoDetectionEnabledSetting(),
                 actualState.getAutoDetectionEnabledSetting());
         assertEquals(config.getGeoDetectionEnabledSetting(),
@@ -1059,7 +1069,7 @@
 
     private GeolocationTimeZoneSuggestion createUncertainGeolocationSuggestion() {
         return GeolocationTimeZoneSuggestion.createCertainSuggestion(
-                mElapsedRealtimeMillis++, null);
+                mFakeEnvironment.elapsedRealtimeMillis(), null);
     }
 
     private GeolocationTimeZoneSuggestion createCertainGeolocationSuggestion(
@@ -1068,54 +1078,42 @@
 
         GeolocationTimeZoneSuggestion suggestion =
                 GeolocationTimeZoneSuggestion.createCertainSuggestion(
-                        mElapsedRealtimeMillis++, Arrays.asList(zoneIds));
+                        mFakeEnvironment.elapsedRealtimeMillis(), Arrays.asList(zoneIds));
         suggestion.addDebugInfo("Test suggestion");
         return suggestion;
     }
 
-    private static TimeZoneConfiguration createConfig(
-            @Nullable Boolean autoDetection, @Nullable Boolean geoDetection) {
-        TimeZoneConfiguration.Builder builder = new TimeZoneConfiguration.Builder();
-        if (autoDetection != null) {
-            builder.setAutoDetectionEnabled(autoDetection);
-        }
-        if (geoDetection != null) {
-            builder.setGeoDetectionEnabled(geoDetection);
-        }
-        return builder.build();
-    }
-
     static class FakeEnvironment implements TimeZoneDetectorStrategyImpl.Environment {
 
-        private final TestState<ConfigurationInternal> mConfigurationInternal = new TestState<>();
         private final TestState<String> mTimeZoneId = new TestState<>();
-        private ConfigurationChangeListener mConfigChangeListener;
+        private ConfigurationInternal mConfigurationInternal;
+        private @ElapsedRealtimeLong long mElapsedRealtimeMillis;
+        private ConfigurationChangeListener mConfigurationInternalChangeListener;
 
         void initializeConfig(ConfigurationInternal configurationInternal) {
-            mConfigurationInternal.init(configurationInternal);
+            mConfigurationInternal = configurationInternal;
+        }
+
+        void initializeClock(@ElapsedRealtimeLong long elapsedRealtimeMillis) {
+            mElapsedRealtimeMillis = elapsedRealtimeMillis;
         }
 
         void initializeTimeZoneSetting(String zoneId) {
             mTimeZoneId.init(zoneId);
         }
 
-        @Override
-        public void setConfigChangeListener(ConfigurationChangeListener listener) {
-            mConfigChangeListener = listener;
+        void incrementClock() {
+            mElapsedRealtimeMillis++;
         }
 
         @Override
-        public ConfigurationInternal getConfigurationInternal(int userId) {
-            ConfigurationInternal configuration = mConfigurationInternal.getLatest();
-            if (userId != configuration.getUserId()) {
-                fail("FakeCallback does not support multiple users.");
-            }
-            return configuration;
+        public void setConfigurationInternalChangeListener(ConfigurationChangeListener listener) {
+            mConfigurationInternalChangeListener = listener;
         }
 
         @Override
-        public int getCurrentUserId() {
-            return mConfigurationInternal.getLatest().getUserId();
+        public ConfigurationInternal getCurrentUserConfigurationInternal() {
+            return mConfigurationInternal;
         }
 
         @Override
@@ -1133,26 +1131,9 @@
             mTimeZoneId.set(zoneId);
         }
 
-        @Override
-        public void storeConfiguration(
-                @UserIdInt int userId, TimeZoneConfiguration newConfiguration) {
-            ConfigurationInternal oldConfiguration = mConfigurationInternal.getLatest();
-            if (userId != oldConfiguration.getUserId()) {
-                fail("FakeCallback does not support multiple users");
-            }
-
-            ConfigurationInternal mergedConfiguration = oldConfiguration.merge(newConfiguration);
-            if (!mergedConfiguration.equals(oldConfiguration)) {
-                mConfigurationInternal.set(mergedConfiguration);
-
-                // Note: Unlike the real callback impl, the listener is invoked synchronously.
-                mConfigChangeListener.onChange();
-            }
-        }
-
-        void assertKnownUser(int userId) {
-            assertEquals("FakeCallback does not support multiple users",
-                    mConfigurationInternal.getLatest().getUserId(), userId);
+        void simulateConfigurationInternalChange(ConfigurationInternal configurationInternal) {
+            mConfigurationInternal = configurationInternal;
+            mConfigurationInternalChangeListener.onChange();
         }
 
         void assertTimeZoneNotChanged() {
@@ -1167,7 +1148,12 @@
 
         void commitAllChanges() {
             mTimeZoneId.commitLatest();
-            mConfigurationInternal.commitLatest();
+        }
+
+        @Override
+        @ElapsedRealtimeLong
+        public long elapsedRealtimeMillis() {
+            return mElapsedRealtimeMillis;
         }
     }
 
@@ -1177,24 +1163,50 @@
      */
     private class Script {
 
-        Script initializeConfig(ConfigurationInternal configuration) {
-            mFakeEnvironment.initializeConfig(configuration);
-            return this;
-        }
-
         Script initializeTimeZoneSetting(String zoneId) {
             mFakeEnvironment.initializeTimeZoneSetting(zoneId);
             return this;
         }
 
+        Script initializeClock(long elapsedRealtimeMillis) {
+            mFakeEnvironment.initializeClock(elapsedRealtimeMillis);
+            return this;
+        }
+
+        Script simulateIncrementClock() {
+            mFakeEnvironment.incrementClock();
+            return this;
+        }
+
         /**
-         * Simulates the time zone detection strategy receiving an updated configuration and checks
-         * the return value.
+         * Simulates the user / user's configuration changing.
          */
-        Script simulateUpdateConfiguration(
-                int userId, TimeZoneConfiguration configuration, boolean expectedResult) {
-            assertEquals(expectedResult,
-                    mTimeZoneDetectorStrategy.updateConfiguration(userId, configuration));
+        Script simulateConfigurationInternalChange(ConfigurationInternal configurationInternal) {
+            mFakeEnvironment.simulateConfigurationInternalChange(configurationInternal);
+            return this;
+        }
+
+        /**
+         * Simulates automatic time zone detection being set to the specified value.
+         */
+        Script simulateSetAutoMode(boolean autoDetectionEnabled) {
+            ConfigurationInternal newConfig = new ConfigurationInternal.Builder(
+                    mFakeEnvironment.getCurrentUserConfigurationInternal())
+                    .setAutoDetectionEnabledSetting(autoDetectionEnabled)
+                    .build();
+            simulateConfigurationInternalChange(newConfig);
+            return this;
+        }
+
+        /**
+         * Simulates automatic geolocation time zone detection being set to the specified value.
+         */
+        Script simulateSetGeoDetectionEnabled(boolean geoDetectionEnabled) {
+            ConfigurationInternal newConfig = new ConfigurationInternal.Builder(
+                    mFakeEnvironment.getCurrentUserConfigurationInternal())
+                    .setGeoDetectionEnabledSetting(geoDetectionEnabled)
+                    .build();
+            simulateConfigurationInternalChange(newConfig);
             return this;
         }
 
@@ -1211,7 +1223,6 @@
         Script simulateManualTimeZoneSuggestion(
                 @UserIdInt int userId, ManualTimeZoneSuggestion manualTimeZoneSuggestion,
                 boolean expectedResult) {
-            mFakeEnvironment.assertKnownUser(userId);
             boolean actualResult = mTimeZoneDetectorStrategy.suggestManualTimeZone(
                     userId, manualTimeZoneSuggestion);
             assertEquals(expectedResult, actualResult);
@@ -1227,6 +1238,15 @@
         }
 
         /**
+         * Simulates the time zone detection strategty receiving a signal that allows it to do
+         * telephony fallback.
+         */
+        Script simulateEnableTelephonyFallback() {
+            mTimeZoneDetectorStrategy.enableTelephonyTimeZoneFallback();
+            return this;
+        }
+
+        /**
          * Confirms that the device's time zone has not been set by previous actions since the test
          * state was last reset.
          */
@@ -1254,29 +1274,18 @@
             return this;
         }
 
-        /**
-         * Verifies that the configuration has been changed to the expected value.
-         */
-        Script verifyConfigurationChangedAndReset(ConfigurationInternal expected) {
-            mFakeEnvironment.mConfigurationInternal.assertHasBeenSet();
-            assertEquals(expected, mFakeEnvironment.mConfigurationInternal.getLatest());
+        Script verifyTimeZoneChangedAndReset(GeolocationTimeZoneSuggestion suggestion) {
+            assertEquals("Only use this method with unambiguous geo suggestions",
+                    1, suggestion.getZoneIds().size());
+            mFakeEnvironment.assertTimeZoneChangedTo(suggestion.getZoneIds().get(0));
             mFakeEnvironment.commitAllChanges();
-
-            // Also confirm the listener triggered.
-            mMockConfigChangeListener.verifyOnChangeCalled();
-            mMockConfigChangeListener.reset();
             return this;
         }
 
-        /**
-         * Verifies that no underlying settings associated with the properties from the
-         * {@link TimeZoneConfiguration} have been changed.
-         */
-        Script verifyConfigurationNotChanged() {
-            mFakeEnvironment.mConfigurationInternal.assertHasNotBeenSet();
-
-            // Also confirm the listener did not trigger.
-            mMockConfigChangeListener.verifyOnChangeNotCalled();
+        /** Verifies the state for telephony fallback. */
+        Script verifyTelephonyFallbackIsEnabled(boolean expectedEnabled) {
+            assertEquals(expectedEnabled,
+                    mTimeZoneDetectorStrategy.isTelephonyFallbackEnabledForTests());
             return this;
         }
 
@@ -1310,25 +1319,4 @@
             @MatchType int matchType, @Quality int quality, int expectedScore) {
         return new TelephonyTestCase(matchType, quality, expectedScore);
     }
-
-    private static class MockConfigChangeListener implements ConfigurationChangeListener {
-        private boolean mOnChangeCalled;
-
-        @Override
-        public void onChange() {
-            mOnChangeCalled = true;
-        }
-
-        void verifyOnChangeCalled() {
-            assertTrue(mOnChangeCalled);
-        }
-
-        void verifyOnChangeNotCalled() {
-            assertFalse(mOnChangeCalled);
-        }
-
-        void reset() {
-            mOnChangeCalled = false;
-        }
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/ControllerImplTest.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
similarity index 68%
rename from services/tests/servicestests/src/com/android/server/timezonedetector/location/ControllerImplTest.java
rename to services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
index 7d6772e..d54e1f1 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/ControllerImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/LocationTimeZoneProviderControllerTest.java
@@ -21,6 +21,14 @@
 import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_INITIALIZING;
 import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STARTED_UNCERTAIN;
 import static com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.PROVIDER_STATE_STOPPED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_CERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_DESTROYED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_FAILED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_INITIALIZING;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_PROVIDERS_INITIALIZING;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_STOPPED;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_UNCERTAIN;
+import static com.android.server.timezonedetector.location.LocationTimeZoneProviderController.STATE_UNKNOWN;
 import static com.android.server.timezonedetector.location.TestSupport.USER1_CONFIG_GEO_DETECTION_DISABLED;
 import static com.android.server.timezonedetector.location.TestSupport.USER1_CONFIG_GEO_DETECTION_ENABLED;
 import static com.android.server.timezonedetector.location.TestSupport.USER2_CONFIG_GEO_DETECTION_ENABLED;
@@ -45,7 +53,9 @@
 import com.android.server.timezonedetector.ConfigurationInternal;
 import com.android.server.timezonedetector.GeolocationTimeZoneSuggestion;
 import com.android.server.timezonedetector.TestState;
+import com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderMetricsLogger;
 import com.android.server.timezonedetector.location.LocationTimeZoneProvider.ProviderState.ProviderStateEnum;
+import com.android.server.timezonedetector.location.LocationTimeZoneProviderController.State;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -57,9 +67,9 @@
 import java.util.List;
 import java.util.Objects;
 
-/** Tests for {@link ControllerImpl}. */
+/** Tests for {@link LocationTimeZoneProviderController}. */
 @Presubmit
-public class ControllerImplTest {
+public class LocationTimeZoneProviderControllerTest {
 
     private static final long ARBITRARY_TIME_MILLIS = 12345L;
 
@@ -73,6 +83,7 @@
             TimeZoneProviderEvent.createPermanentFailureEvent(ARBITRARY_TIME_MILLIS, "Test");
 
     private TestThreadingDomain mTestThreadingDomain;
+    private TestMetricsLogger mTestMetricsLogger;
     private TestCallback mTestCallback;
     private TestLocationTimeZoneProvider mTestPrimaryLocationTimeZoneProvider;
     private TestLocationTimeZoneProvider mTestSecondaryLocationTimeZoneProvider;
@@ -82,11 +93,12 @@
         // For simplicity, the TestThreadingDomain uses the test's main thread. To execute posted
         // runnables, the test must call methods on mTestThreadingDomain otherwise those runnables
         // will never get a chance to execute.
-        LocationTimeZoneProvider.ProviderMetricsLogger stubbedProviderMetricsLogger = stateEnum -> {
-            // Stubbed.
-        };
         mTestThreadingDomain = new TestThreadingDomain();
+        mTestMetricsLogger = new TestMetricsLogger();
+
         mTestCallback = new TestCallback(mTestThreadingDomain);
+
+        ProviderMetricsLogger stubbedProviderMetricsLogger = stateEnum -> {};
         mTestPrimaryLocationTimeZoneProvider = new TestLocationTimeZoneProvider(
                 stubbedProviderMetricsLogger, mTestThreadingDomain, "primary");
         mTestSecondaryLocationTimeZoneProvider = new TestLocationTimeZoneProvider(
@@ -94,11 +106,20 @@
     }
 
     @Test
+    public void controllerStartsInUnknownState() {
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
+        assertControllerState(controller, STATE_UNKNOWN);
+    }
+
+    @Test
     public void initializationFailure_primary() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
         Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
                 .plus(testEnvironment.getProviderInitializationTimeoutFuzz());
 
@@ -106,25 +127,29 @@
 
         // Initialize. After initialization the providers must be initialized and one should be
         // started.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertInitialized();
         mTestSecondaryLocationTimeZoneProvider.assertInitialized();
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void initializationFailure_secondary() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
         Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
                 .plus(testEnvironment.getProviderInitializationTimeoutFuzz());
 
@@ -132,387 +157,460 @@
 
         // Initialize. After initialization the providers must be initialized and one should be
         // started.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertInitialized();
         mTestSecondaryLocationTimeZoneProvider.assertInitialized();
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestPrimaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void initializationFailure_both() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         mTestPrimaryLocationTimeZoneProvider.setFailDuringInitialization(true);
         mTestSecondaryLocationTimeZoneProvider.setFailDuringInitialization(true);
 
         // Initialize. After initialization the providers must be initialized and one should be
         // started.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertInitialized();
         mTestSecondaryLocationTimeZoneProvider.assertInitialized();
 
+        assertControllerState(controller, STATE_FAILED);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING, STATE_FAILED);
         mTestCallback.assertUncertainSuggestionMadeAndCommit();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void initialState_started() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
         Duration expectedInitTimeout = testEnvironment.getProviderInitializationTimeout()
                 .plus(testEnvironment.getProviderInitializationTimeoutFuzz());
 
         // Initialize. After initialization the providers must be initialized and one should be
         // started.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertInitialized();
         mTestSecondaryLocationTimeZoneProvider.assertInitialized();
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestPrimaryLocationTimeZoneProvider.assertInitializationTimeoutSet(expectedInitTimeout);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void initialState_disabled() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_DISABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_DISABLED);
 
         // Initialize. After initialization the providers must be initialized but neither should be
         // started.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertInitialized();
         mTestSecondaryLocationTimeZoneProvider.assertInitialized();
 
+        assertControllerState(controller, STATE_STOPPED);
         mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_PROVIDERS_INITIALIZING, STATE_STOPPED);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void enabled_uncertaintySuggestionSentIfNoEventReceived() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate time passing with no provider event being received from the primary.
         mTestThreadingDomain.executeNext();
 
+        assertControllerState(controller, STATE_INITIALIZING);
         // The primary should have reported uncertainty, which should trigger the controller to
         // start the uncertainty timeout and start the secondary.
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // Simulate time passing with no provider event being received from either the primary or
         // secondary.
         mTestThreadingDomain.executeNext();
 
+        assertControllerState(controller, STATE_INITIALIZING);
         // Now both initialization timeouts should have triggered. The uncertainty timeout should
         // still not be triggered.
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // Finally, the uncertainty timeout should cause the controller to make an uncertain
         // suggestion.
         mTestThreadingDomain.executeNext();
 
+        assertControllerState(controller, STATE_UNCERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN);
         mTestCallback.assertUncertainSuggestionMadeAndCommit();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void enabled_eventReceivedBeforeInitializationTimeout() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate a location event being received from the primary provider. This should cause a
         // suggestion to be made.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void enabled_eventReceivedFromPrimaryAfterInitializationTimeout() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate time passing with no provider event being received from the primary.
         mTestThreadingDomain.executeNext();
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // Simulate a location event being received from the primary provider. This should cause a
         // suggestion to be made and the secondary to be shut down.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void enabled_eventReceivedFromSecondaryAfterInitializationTimeout() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate time passing with no provider event being received from the primary.
         mTestThreadingDomain.executeNext();
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // Simulate a location event being received from the secondary provider. This should cause a
         // suggestion to be made.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void enabled_repeatedPrimaryCertainty() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate a location event being received from the primary provider. This should cause a
         // suggestion to be made.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // A second, identical event should not cause another suggestion.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // And a third, different event should cause another suggestion.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void enabled_repeatedSecondaryCertainty() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate time passing with no provider event being received from the primary.
         mTestThreadingDomain.executeNext();
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // Simulate a location event being received from the secondary provider. This should cause a
         // suggestion to be made.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // A second, identical event should not cause another suggestion.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // And a third, different event should cause another suggestion.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void enabled_uncertaintyTriggersASuggestionAfterUncertaintyTimeout() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate a location event being received from the primary provider. This should cause a
         // suggestion to be made and ensure the primary is considered initialized.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate an uncertain event being received from the primary provider. This should not
         // cause a suggestion to be made straight away, but the uncertainty timeout should be
@@ -520,12 +618,14 @@
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // Simulate a location event being received from the secondary provider. This should cause a
         // suggestion to be made, cancel the uncertainty timeout and ensure the secondary is
@@ -533,13 +633,15 @@
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate an uncertain event being received from the secondary provider. This should not
         // cause a suggestion to be made straight away, but the uncertainty timeout should be
@@ -547,65 +649,77 @@
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // Simulate time passing. This means the uncertainty timeout should fire and the uncertain
         // suggestion should be made.
         mTestThreadingDomain.executeNext();
 
+        assertControllerState(controller, STATE_UNCERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN);
         mTestCallback.assertUncertainSuggestionMadeFromEventAndCommit(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void enabled_briefUncertaintyTriggersNoSuggestion() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate a location event being received from the primary provider. This should cause a
         // suggestion to be made.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Uncertainty should not cause a suggestion to be made straight away, but the uncertainty
         // timeout should be started and the secondary should be started.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // And a success event from the primary provider should cause the controller to make another
         // suggestion, the uncertainty timeout should be cancelled and the secondary should be
@@ -613,81 +727,97 @@
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void configChanges_enableAndDisableWithNoPreviousSuggestion() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_DISABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_DISABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_STOPPED);
         mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_PROVIDERS_INITIALIZING, STATE_STOPPED);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Now signal a config change so that geo detection is enabled.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Now signal a config change so that geo detection is disabled.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
 
+        assertControllerState(controller, STATE_STOPPED);
         mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_STOPPED);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void configChanges_enableAndDisableWithPreviousSuggestion() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_DISABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_DISABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_STOPPED);
         mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_PROVIDERS_INITIALIZING, STATE_STOPPED);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Now signal a config change so that geo detection is enabled.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate a success event being received from the primary provider.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Now signal a config change so that geo detection is disabled.
         // Because there had been a previous suggestion, the controller should withdraw it
@@ -695,27 +825,33 @@
         // of the time zone.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
 
+        assertControllerState(controller, STATE_STOPPED);
         mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_UNCERTAIN, STATE_STOPPED);
         mTestCallback.assertUncertainSuggestionMadeAndCommit();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void configChanges_userSwitch_enabledToEnabled() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate the primary provider suggesting a time zone.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -723,18 +859,20 @@
 
         // Receiving a "success" provider event should cause a suggestion to be made synchronously,
         // and also clear the scheduled uncertainty suggestion.
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate the user change (but geo detection still enabled).
         testEnvironment.simulateConfigChange(USER2_CONFIG_GEO_DETECTION_ENABLED);
 
         // Confirm that the previous suggestion was overridden.
-        mTestCallback.assertUncertainSuggestionMadeAndCommit();
+        assertControllerState(controller, STATE_INITIALIZING);
 
         // We expect the provider to end up in PROVIDER_STATE_STARTED_INITIALIZING, but it should
         // have been stopped when the user changed.
@@ -744,129 +882,158 @@
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfig(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER2_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_UNCERTAIN, STATE_STOPPED, STATE_INITIALIZING);
+        mTestCallback.assertUncertainSuggestionMadeAndCommit();
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void primaryPermFailure_secondaryEventsReceived() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate a failure location event being received from the primary provider. This should
         // cause the secondary to be started.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate uncertainty from the secondary.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // And a success event from the secondary provider should cause the controller to make
         // another suggestion, the uncertainty timeout should be cancelled.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate uncertainty from the secondary.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
     }
 
     @Test
     public void primaryPermFailure_disableAndEnable() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate a failure location event being received from the primary provider. This should
         // cause the secondary to be started.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Now signal a config change so that geo detection is disabled.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
 
+        assertControllerState(controller, STATE_STOPPED);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_STOPPED);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Now signal a config change so that geo detection is enabled.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void secondaryPermFailure_primaryEventsReceived() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate an uncertain event from the primary. This will start the secondary, which will
         // give this test the opportunity to simulate its failure. Then it will be possible to
@@ -874,61 +1041,73 @@
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // Simulate failure event from the secondary. This should just affect the secondary's state.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // And a success event from the primary provider should cause the controller to make
         // a suggestion, the uncertainty timeout should be cancelled.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT2);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate uncertainty from the primary. The secondary cannot be started.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
     }
 
     @Test
     public void secondaryPermFailure_disableAndEnable() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate an uncertain event from the primary. This will start the secondary, which will
         // give this test the opportunity to simulate its failure. Then it will be possible to
@@ -936,97 +1115,117 @@
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // Simulate failure event from the secondary. This should just affect the secondary's state.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_UNCERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertUncertaintyTimeoutSet(testEnvironment, controllerImpl);
+        assertUncertaintyTimeoutSet(testEnvironment, controller);
 
         // Now signal a config change so that geo detection is disabled.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_DISABLED);
 
+        assertControllerState(controller, STATE_STOPPED);
         mTestPrimaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_STOPPED);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Now signal a config change so that geo detection is enabled. Only the primary can be
         // started.
         testEnvironment.simulateConfigChange(USER1_CONFIG_GEO_DETECTION_ENABLED);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void bothPermFailure_disableAndEnable() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate a failure event from the primary. This will start the secondary.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
+        mTestMetricsLogger.assertStateChangesAndCommit();
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate failure event from the secondary.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_PERM_FAILURE_LOCATION_TIME_ZONE_EVENT);
 
+        assertControllerState(controller, STATE_FAILED);
         mTestPrimaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
         mTestSecondaryLocationTimeZoneProvider.assertIsPermFailedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_FAILED);
         mTestCallback.assertUncertainSuggestionMadeAndCommit();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     @Test
     public void stateRecording() {
         // The test provider enables state recording by default.
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, true /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial states.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
         {
-            LocationTimeZoneManagerServiceState state = controllerImpl.getStateForTests();
+            LocationTimeZoneManagerServiceState state = controller.getStateForTests();
+            assertEquals(STATE_INITIALIZING, state.getControllerState());
             assertNull(state.getLastSuggestion());
+            assertControllerRecordedStates(state,
+                    STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
             assertProviderStates(state.getPrimaryProviderStates(),
                     PROVIDER_STATE_STOPPED, PROVIDER_STATE_STARTED_INITIALIZING);
             assertProviderStates(state.getSecondaryProviderStates(), PROVIDER_STATE_STOPPED);
         }
-        controllerImpl.clearRecordedProviderStates();
+        controller.clearRecordedStates();
 
         // Simulate some provider behavior that will show up in the state recording.
 
@@ -1035,33 +1234,39 @@
                 USER1_UNCERTAIN_LOCATION_TIME_ZONE_EVENT);
 
         {
-            LocationTimeZoneManagerServiceState state = controllerImpl.getStateForTests();
+            LocationTimeZoneManagerServiceState state = controller.getStateForTests();
+            assertEquals(STATE_INITIALIZING, state.getControllerState());
             assertNull(state.getLastSuggestion());
+            assertControllerRecordedStates(state);
             assertProviderStates(
                     state.getPrimaryProviderStates(), PROVIDER_STATE_STARTED_UNCERTAIN);
             assertProviderStates(
                     state.getSecondaryProviderStates(), PROVIDER_STATE_STARTED_INITIALIZING);
         }
-        controllerImpl.clearRecordedProviderStates();
+        controller.clearRecordedStates();
 
         // Simulate a certain event from the secondary.
         mTestSecondaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
 
         {
-            LocationTimeZoneManagerServiceState state = controllerImpl.getStateForTests();
+            LocationTimeZoneManagerServiceState state = controller.getStateForTests();
+            assertEquals(STATE_CERTAIN, state.getControllerState());
             assertEquals(USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds(),
                     state.getLastSuggestion().getZoneIds());
+            assertControllerRecordedStates(state, STATE_CERTAIN);
             assertProviderStates(state.getPrimaryProviderStates());
             assertProviderStates(
                     state.getSecondaryProviderStates(), PROVIDER_STATE_STARTED_CERTAIN);
         }
 
-        controllerImpl.clearRecordedProviderStates();
+        controller.clearRecordedStates();
         {
-            LocationTimeZoneManagerServiceState state = controllerImpl.getStateForTests();
+            LocationTimeZoneManagerServiceState state = controller.getStateForTests();
+            assertEquals(STATE_CERTAIN, state.getControllerState());
             assertEquals(USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1.getSuggestion().getTimeZoneIds(),
                     state.getLastSuggestion().getZoneIds());
+            assertControllerRecordedStates(state);
             assertProviderStates(state.getPrimaryProviderStates());
             assertProviderStates(state.getSecondaryProviderStates());
         }
@@ -1078,19 +1283,23 @@
 
     @Test
     public void destroy() {
-        ControllerImpl controllerImpl = new ControllerImpl(mTestThreadingDomain,
-                mTestPrimaryLocationTimeZoneProvider, mTestSecondaryLocationTimeZoneProvider);
+        LocationTimeZoneProviderController controller = new LocationTimeZoneProviderController(
+                mTestThreadingDomain, mTestMetricsLogger, mTestPrimaryLocationTimeZoneProvider,
+                mTestSecondaryLocationTimeZoneProvider, false /* recordStateChanges */);
         TestEnvironment testEnvironment = new TestEnvironment(
-                mTestThreadingDomain, controllerImpl, USER1_CONFIG_GEO_DETECTION_ENABLED);
+                mTestThreadingDomain, controller, USER1_CONFIG_GEO_DETECTION_ENABLED);
 
         // Initialize and check initial state.
-        controllerImpl.initialize(testEnvironment, mTestCallback);
+        controller.initialize(testEnvironment, mTestCallback);
 
+        assertControllerState(controller, STATE_INITIALIZING);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_INITIALIZING, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_PROVIDERS_INITIALIZING, STATE_STOPPED, STATE_INITIALIZING);
         mTestCallback.assertNoSuggestionMade();
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Simulate the primary provider suggesting a time zone.
         mTestPrimaryLocationTimeZoneProvider.simulateTimeZoneProviderEvent(
@@ -1098,15 +1307,21 @@
 
         // Receiving a "success" provider event should cause a suggestion to be made synchronously,
         // and also clear the scheduled uncertainty suggestion.
+        assertControllerState(controller, STATE_CERTAIN);
         mTestPrimaryLocationTimeZoneProvider.assertStateEnumAndConfigAndCommit(
                 PROVIDER_STATE_STARTED_CERTAIN, USER1_CONFIG_GEO_DETECTION_ENABLED);
         mTestSecondaryLocationTimeZoneProvider.assertIsStoppedAndCommit();
+        mTestMetricsLogger.assertStateChangesAndCommit(STATE_CERTAIN);
         mTestCallback.assertCertainSuggestionMadeFromEventAndCommit(
                 USER1_SUCCESS_LOCATION_TIME_ZONE_EVENT1);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
 
         // Trigger destroy().
-        controllerImpl.destroy();
+        controller.destroy();
+
+        assertControllerState(controller, STATE_DESTROYED);
+        mTestMetricsLogger.assertStateChangesAndCommit(
+                STATE_UNCERTAIN, STATE_STOPPED, STATE_DESTROYED);
 
         // Confirm that the previous suggestion was overridden.
         mTestCallback.assertUncertainSuggestionMadeAndCommit();
@@ -1115,7 +1330,7 @@
                 PROVIDER_STATE_STOPPED, PROVIDER_STATE_DESTROYED);
         mTestSecondaryLocationTimeZoneProvider.assertStateChangesAndCommit(
                 PROVIDER_STATE_DESTROYED);
-        assertFalse(controllerImpl.isUncertaintyTimeoutSet());
+        assertFalse(controller.isUncertaintyTimeoutSet());
     }
 
     private static void assertUncertaintyTimeoutSet(
@@ -1135,6 +1350,17 @@
                         .build());
     }
 
+    private static void assertControllerState(LocationTimeZoneProviderController controller,
+            @State String expectedState) {
+        assertEquals(expectedState, controller.getStateForTests().getControllerState());
+    }
+
+    private static void assertControllerRecordedStates(
+            LocationTimeZoneManagerServiceState state,
+            @State String... expectedStates) {
+        assertEquals(Arrays.asList(expectedStates), state.getControllerStates());
+    }
+
     private static class TestEnvironment extends LocationTimeZoneProviderController.Environment {
 
         // These timeouts are set deliberately so that:
@@ -1202,7 +1428,23 @@
             if (Objects.equals(oldConfig, newConfig)) {
                 fail("Bad test? No config change when one was expected");
             }
-            mController.onConfigChanged();
+            mController.onConfigurationInternalChanged();
+        }
+    }
+
+    private static class TestMetricsLogger
+            implements LocationTimeZoneProviderController.MetricsLogger {
+
+        private final TestState<@State String> mLatestStateEnum = new TestState<>();
+
+        @Override
+        public void onStateChange(@State String stateEnum) {
+            mLatestStateEnum.set(stateEnum);
+        }
+
+        public void assertStateChangesAndCommit(@State String... expectedStateEnums) {
+            mLatestStateEnum.assertChanges(expectedStateEnums);
+            mLatestStateEnum.commitLatest();
         }
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java
index 16ac1d6..a2df3130 100644
--- a/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java
+++ b/services/tests/servicestests/src/com/android/server/timezonedetector/location/TestSupport.java
@@ -41,14 +41,15 @@
     }
 
     private static ConfigurationInternal createUserConfig(
-            @UserIdInt int userId, boolean geoDetectionEnabled) {
+            @UserIdInt int userId, boolean geoDetectionEnabledSetting) {
         return new ConfigurationInternal.Builder(userId)
                 .setUserConfigAllowed(true)
                 .setTelephonyDetectionFeatureSupported(true)
                 .setGeoDetectionFeatureSupported(true)
-                .setAutoDetectionEnabled(true)
-                .setLocationEnabled(true)
-                .setGeoDetectionEnabled(geoDetectionEnabled)
+                .setTelephonyFallbackSupported(false)
+                .setAutoDetectionEnabledSetting(true)
+                .setLocationEnabledSetting(true)
+                .setGeoDetectionEnabledSetting(geoDetectionEnabledSetting)
                 .build();
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibrator.java b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibrator.java
index e739a76..e2a348e 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/FakeVibrator.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/FakeVibrator.java
@@ -16,12 +16,11 @@
 
 package com.android.server.vibrator;
 
+import android.annotation.NonNull;
 import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
 
-import androidx.annotation.NonNull;
-
 /** Fake implementation of {@link Vibrator} for service tests. */
 final class FakeVibrator extends Vibrator {
 
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
index 7d24a2f..beee2a7 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibrationSettingsTest.java
@@ -16,6 +16,19 @@
 
 package com.android.server.vibrator;
 
+import static android.os.VibrationAttributes.USAGE_ALARM;
+import static android.os.VibrationAttributes.USAGE_COMMUNICATION_REQUEST;
+import static android.os.VibrationAttributes.USAGE_HARDWARE_FEEDBACK;
+import static android.os.VibrationAttributes.USAGE_NOTIFICATION;
+import static android.os.VibrationAttributes.USAGE_PHYSICAL_EMULATION;
+import static android.os.VibrationAttributes.USAGE_RINGTONE;
+import static android.os.VibrationAttributes.USAGE_TOUCH;
+import static android.os.VibrationAttributes.USAGE_UNKNOWN;
+import static android.os.Vibrator.VIBRATION_INTENSITY_HIGH;
+import static android.os.Vibrator.VIBRATION_INTENSITY_LOW;
+import static android.os.Vibrator.VIBRATION_INTENSITY_MEDIUM;
+import static android.os.Vibrator.VIBRATION_INTENSITY_OFF;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -39,9 +52,7 @@
 import android.os.PowerManagerInternal;
 import android.os.PowerSaveState;
 import android.os.UserHandle;
-import android.os.VibrationAttributes;
 import android.os.VibrationEffect;
-import android.os.Vibrator;
 import android.os.test.TestLooper;
 import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
@@ -70,16 +81,19 @@
 public class VibrationSettingsTest {
 
     private static final int UID = 1;
-    private static final int USER_OPERATION_TIMEOUT_MILLIS = 60_000; // 1 min
     private static final PowerSaveState NORMAL_POWER_STATE = new PowerSaveState.Builder().build();
     private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder()
             .setBatterySaverEnabled(true).build();
 
-    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
-    @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
+    @Rule
+    public MockitoRule mMockitoRule = MockitoJUnit.rule();
+    @Rule
+    public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
 
-    @Mock private VibrationSettings.OnVibratorSettingsChanged mListenerMock;
-    @Mock private PowerManagerInternal mPowerManagerInternalMock;
+    @Mock
+    private VibrationSettings.OnVibratorSettingsChanged mListenerMock;
+    @Mock
+    private PowerManagerInternal mPowerManagerInternalMock;
 
     private TestLooper mTestLooper;
     private ContextWrapper mContextSpy;
@@ -112,7 +126,7 @@
 
         setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 0);
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
-        setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
+        setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
         setGlobalSetting(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
     }
 
@@ -127,16 +141,14 @@
 
         setUserSetting(Settings.System.VIBRATE_INPUT_DEVICES, 1);
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
-        setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
+        setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
         setGlobalSetting(Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_ALARMS);
-        setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_OFF);
-        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_OFF);
-        setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
 
-        verify(mListenerMock, times(7)).onChange();
+        verify(mListenerMock, times(8)).onChange();
     }
 
     @Test
@@ -171,89 +183,83 @@
         VibrationSettings vibrationSettings = new VibrationSettings(mContextSpy,
                 new Handler(mTestLooper.getLooper()));
 
-        assertFalse(vibrationSettings.shouldVibrateForRingerMode(
-                VibrationAttributes.USAGE_RINGTONE));
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_ALARM));
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_TOUCH));
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(
-                VibrationAttributes.USAGE_NOTIFICATION));
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(
-                VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
+        assertFalse(vibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_ALARM));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_TOUCH));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_NOTIFICATION));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_COMMUNICATION_REQUEST));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_HARDWARE_FEEDBACK));
     }
 
     @Test
     public void shouldVibrateForRingerMode_withoutRingtoneUsage_returnsTrue() {
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_ALARM));
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(VibrationAttributes.USAGE_TOUCH));
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(
-                VibrationAttributes.USAGE_NOTIFICATION));
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(
-                VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_ALARM));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_TOUCH));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_NOTIFICATION));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_COMMUNICATION_REQUEST));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_HARDWARE_FEEDBACK));
     }
 
     @Test
     public void shouldVibrateForRingerMode_withVibrateWhenRinging_ignoreSettingsForSilentMode() {
-        int usageRingtone = VibrationAttributes.USAGE_RINGTONE;
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
 
         setRingerMode(AudioManager.RINGER_MODE_SILENT);
-        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
 
         setRingerMode(AudioManager.RINGER_MODE_MAX);
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
 
         setRingerMode(AudioManager.RINGER_MODE_NORMAL);
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
 
         setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
     }
 
     @Test
     public void shouldVibrateForRingerMode_withApplyRampingRinger_ignoreSettingsForSilentMode() {
-        int usageRingtone = VibrationAttributes.USAGE_RINGTONE;
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
-        setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 1);
+        setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1);
 
         setRingerMode(AudioManager.RINGER_MODE_SILENT);
-        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
 
         setRingerMode(AudioManager.RINGER_MODE_MAX);
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
 
         setRingerMode(AudioManager.RINGER_MODE_NORMAL);
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
 
         setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
     }
 
     @Test
     public void shouldVibrateForRingerMode_withAllSettingsOff_onlyVibratesForVibrateMode() {
-        int usageRingtone = VibrationAttributes.USAGE_RINGTONE;
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
-        setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
+        setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
 
         setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
-        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertTrue(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
 
         setRingerMode(AudioManager.RINGER_MODE_SILENT);
-        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
 
         setRingerMode(AudioManager.RINGER_MODE_MAX);
-        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
 
         setRingerMode(AudioManager.RINGER_MODE_NORMAL);
-        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(usageRingtone));
+        assertFalse(mVibrationSettings.shouldVibrateForRingerMode(USAGE_RINGTONE));
     }
 
     @Test
     public void shouldVibrateForUid_withForegroundOnlyUsage_returnsTrueWhInForeground() {
-        assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_TOUCH));
+        assertTrue(mVibrationSettings.shouldVibrateForUid(UID, USAGE_TOUCH));
 
         mVibrationSettings.mUidObserver.onUidStateChanged(
                 UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
-        assertFalse(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_TOUCH));
+        assertFalse(mVibrationSettings.shouldVibrateForUid(UID, USAGE_TOUCH));
     }
 
     @Test
@@ -261,38 +267,32 @@
         mVibrationSettings.mUidObserver.onUidStateChanged(
                 UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND, 0, 0);
 
-        assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_ALARM));
-        assertTrue(mVibrationSettings.shouldVibrateForUid(UID,
-                VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
-        assertTrue(mVibrationSettings.shouldVibrateForUid(UID,
-                VibrationAttributes.USAGE_NOTIFICATION));
-        assertTrue(mVibrationSettings.shouldVibrateForUid(UID, VibrationAttributes.USAGE_RINGTONE));
+        assertTrue(mVibrationSettings.shouldVibrateForUid(UID, USAGE_ALARM));
+        assertTrue(mVibrationSettings.shouldVibrateForUid(UID, USAGE_COMMUNICATION_REQUEST));
+        assertTrue(mVibrationSettings.shouldVibrateForUid(UID, USAGE_NOTIFICATION));
+        assertTrue(mVibrationSettings.shouldVibrateForUid(UID, USAGE_RINGTONE));
     }
 
     @Test
     public void shouldVibrateForPowerMode_withLowPowerAndAllowedUsage_returnTrue() {
         mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
 
-        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_ALARM));
-        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(
-                VibrationAttributes.USAGE_RINGTONE));
-        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(
-                VibrationAttributes.USAGE_COMMUNICATION_REQUEST));
+        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(USAGE_ALARM));
+        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(USAGE_RINGTONE));
+        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(USAGE_COMMUNICATION_REQUEST));
     }
 
     @Test
     public void shouldVibrateForPowerMode_withRestrictedUsage_returnsFalseWhileInLowPowerMode() {
         mRegisteredPowerModeListener.onLowPowerModeChanged(NORMAL_POWER_STATE);
 
-        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_TOUCH));
-        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(
-                VibrationAttributes.USAGE_NOTIFICATION));
+        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(USAGE_TOUCH));
+        assertTrue(mVibrationSettings.shouldVibrateForPowerMode(USAGE_NOTIFICATION));
 
         mRegisteredPowerModeListener.onLowPowerModeChanged(LOW_POWER_STATE);
 
-        assertFalse(mVibrationSettings.shouldVibrateForPowerMode(VibrationAttributes.USAGE_TOUCH));
-        assertFalse(mVibrationSettings.shouldVibrateForPowerMode(
-                VibrationAttributes.USAGE_NOTIFICATION));
+        assertFalse(mVibrationSettings.shouldVibrateForPowerMode(USAGE_TOUCH));
+        assertFalse(mVibrationSettings.shouldVibrateForPowerMode(USAGE_NOTIFICATION));
     }
 
     @Test
@@ -324,108 +324,128 @@
 
     @Test
     public void getDefaultIntensity_beforeSystemReady_returnsMediumToAllExceptAlarm() {
-        mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
-        mFakeVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
-        mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
+        mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_HIGH);
+        mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_HIGH);
+        mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_HIGH);
 
-        setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_OFF);
-        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_OFF);
-        setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
 
         VibrationSettings vibrationSettings = new VibrationSettings(mContextSpy,
                 new Handler(mTestLooper.getLooper()));
 
-        assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
-                vibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_ALARM));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
-                vibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_TOUCH));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
-                vibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
-                vibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_UNKNOWN));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
-                vibrationSettings.getDefaultIntensity(
-                        VibrationAttributes.USAGE_PHYSICAL_EMULATION));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
-                vibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE));
+        assertEquals(VIBRATION_INTENSITY_HIGH,
+                vibrationSettings.getDefaultIntensity(USAGE_ALARM));
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                vibrationSettings.getDefaultIntensity(USAGE_TOUCH));
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                vibrationSettings.getDefaultIntensity(USAGE_HARDWARE_FEEDBACK));
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                vibrationSettings.getDefaultIntensity(USAGE_PHYSICAL_EMULATION));
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                vibrationSettings.getDefaultIntensity(USAGE_NOTIFICATION));
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                vibrationSettings.getDefaultIntensity(USAGE_UNKNOWN));
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                vibrationSettings.getDefaultIntensity(USAGE_RINGTONE));
     }
 
     @Test
     public void getDefaultIntensity_returnsIntensityFromVibratorService() {
-        mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_HIGH);
-        mFakeVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_MEDIUM);
-        mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_LOW);
+        mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_HIGH);
+        mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_MEDIUM);
+        mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_LOW);
 
-        setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_OFF);
-        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_OFF);
-        setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
 
-        assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
-                mVibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_ALARM));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
-                mVibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_TOUCH));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
-                mVibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_NOTIFICATION));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
-                mVibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_UNKNOWN));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
-                mVibrationSettings.getDefaultIntensity(
-                        VibrationAttributes.USAGE_PHYSICAL_EMULATION));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_LOW,
-                mVibrationSettings.getDefaultIntensity(VibrationAttributes.USAGE_RINGTONE));
+        assertEquals(VIBRATION_INTENSITY_HIGH,
+                mVibrationSettings.getDefaultIntensity(USAGE_ALARM));
+        assertEquals(VIBRATION_INTENSITY_HIGH,
+                mVibrationSettings.getDefaultIntensity(USAGE_TOUCH));
+        assertEquals(VIBRATION_INTENSITY_HIGH,
+                mVibrationSettings.getDefaultIntensity(USAGE_HARDWARE_FEEDBACK));
+        assertEquals(VIBRATION_INTENSITY_HIGH,
+                mVibrationSettings.getDefaultIntensity(USAGE_PHYSICAL_EMULATION));
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                mVibrationSettings.getDefaultIntensity(USAGE_NOTIFICATION));
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                mVibrationSettings.getDefaultIntensity(USAGE_UNKNOWN));
+        assertEquals(VIBRATION_INTENSITY_LOW,
+                mVibrationSettings.getDefaultIntensity(USAGE_RINGTONE));
     }
 
     @Test
     public void getCurrentIntensity_returnsIntensityFromSettings() {
-        mFakeVibrator.setDefaultHapticFeedbackIntensity(Vibrator.VIBRATION_INTENSITY_OFF);
-        mFakeVibrator.setDefaultNotificationVibrationIntensity(Vibrator.VIBRATION_INTENSITY_OFF);
-        mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_OFF);
+        mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_OFF);
+        mFakeVibrator.setDefaultNotificationVibrationIntensity(VIBRATION_INTENSITY_OFF);
+        mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_OFF);
 
-        setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_HIGH);
+        setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH);
+        setUserSetting(Settings.System.HARDWARE_HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_LOW);
         setUserSetting(Settings.System.NOTIFICATION_VIBRATION_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_MEDIUM);
-        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_LOW);
+                VIBRATION_INTENSITY_MEDIUM);
+        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW);
 
-        assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
-                mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_ALARM));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
-                mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_TOUCH));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
-                mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_NOTIFICATION));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
-                mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_UNKNOWN));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_MEDIUM,
-                mVibrationSettings.getCurrentIntensity(
-                        VibrationAttributes.USAGE_PHYSICAL_EMULATION));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_LOW,
-                mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_RINGTONE));
+        assertEquals(VIBRATION_INTENSITY_HIGH, mVibrationSettings.getCurrentIntensity(USAGE_ALARM));
+        assertEquals(VIBRATION_INTENSITY_HIGH, mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
+        assertEquals(VIBRATION_INTENSITY_LOW,
+                mVibrationSettings.getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
+        assertEquals(VIBRATION_INTENSITY_LOW,
+                mVibrationSettings.getCurrentIntensity(USAGE_PHYSICAL_EMULATION));
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                mVibrationSettings.getCurrentIntensity(USAGE_NOTIFICATION));
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                mVibrationSettings.getCurrentIntensity(USAGE_UNKNOWN));
+        assertEquals(VIBRATION_INTENSITY_LOW,
+                mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
     }
 
     @Test
     public void getCurrentIntensity_updateTriggeredAfterUserSwitched() {
-        mFakeVibrator.setDefaultRingVibrationIntensity(Vibrator.VIBRATION_INTENSITY_OFF);
-        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY,
-                Vibrator.VIBRATION_INTENSITY_HIGH);
-        assertEquals(Vibrator.VIBRATION_INTENSITY_HIGH,
-                mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_RINGTONE));
+        mFakeVibrator.setDefaultRingVibrationIntensity(VIBRATION_INTENSITY_OFF);
+        setUserSetting(Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_HIGH);
+        assertEquals(VIBRATION_INTENSITY_HIGH,
+                mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
 
         // Switching user is not working with FakeSettingsProvider.
         // Testing the broadcast flow manually.
         Settings.System.putIntForUser(mContextSpy.getContentResolver(),
-                Settings.System.RING_VIBRATION_INTENSITY, Vibrator.VIBRATION_INTENSITY_LOW,
+                Settings.System.RING_VIBRATION_INTENSITY, VIBRATION_INTENSITY_LOW,
                 UserHandle.USER_CURRENT);
         mVibrationSettings.mUserReceiver.onReceive(mContextSpy,
                 new Intent(Intent.ACTION_USER_SWITCHED));
-        assertEquals(Vibrator.VIBRATION_INTENSITY_LOW,
-                mVibrationSettings.getCurrentIntensity(VibrationAttributes.USAGE_RINGTONE));
+        assertEquals(VIBRATION_INTENSITY_LOW,
+                mVibrationSettings.getCurrentIntensity(USAGE_RINGTONE));
+    }
+
+    @Test
+    public void getCurrentIntensity_noHardwareFeedbackValueUsesHapticFeedbackValue() {
+        mFakeVibrator.setDefaultHapticFeedbackIntensity(VIBRATION_INTENSITY_MEDIUM);
+        setUserSetting(Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_OFF);
+        assertEquals(VIBRATION_INTENSITY_OFF, mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
+        // If haptic feedback is off, fallback to default value.
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                mVibrationSettings.getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
+        assertEquals(VIBRATION_INTENSITY_MEDIUM,
+                mVibrationSettings.getCurrentIntensity(USAGE_PHYSICAL_EMULATION));
+
+        // Switching user is not working with FakeSettingsProvider.
+        // Testing the broadcast flow manually.
+        Settings.System.putIntForUser(mContextSpy.getContentResolver(),
+                Settings.System.HAPTIC_FEEDBACK_INTENSITY, VIBRATION_INTENSITY_HIGH,
+                UserHandle.USER_CURRENT);
+        mVibrationSettings.mUserReceiver.onReceive(mContextSpy,
+                new Intent(Intent.ACTION_USER_SWITCHED));
+        assertEquals(VIBRATION_INTENSITY_HIGH,
+                mVibrationSettings.getCurrentIntensity(USAGE_TOUCH));
+        assertEquals(VIBRATION_INTENSITY_HIGH,
+                mVibrationSettings.getCurrentIntensity(USAGE_HARDWARE_FEEDBACK));
+        assertEquals(VIBRATION_INTENSITY_HIGH,
+                mVibrationSettings.getCurrentIntensity(USAGE_PHYSICAL_EMULATION));
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index 6118169..c0f7596 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -118,8 +118,7 @@
     private static final VibrationAttributes ALARM_ATTRS =
             new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_ALARM).build();
     private static final VibrationAttributes HAPTIC_FEEDBACK_ATTRS =
-            new VibrationAttributes.Builder().setUsage(
-                    VibrationAttributes.USAGE_TOUCH).build();
+            new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_TOUCH).build();
     private static final VibrationAttributes NOTIFICATION_ATTRS =
             new VibrationAttributes.Builder().setUsage(
                     VibrationAttributes.USAGE_NOTIFICATION).build();
@@ -127,15 +126,23 @@
             new VibrationAttributes.Builder().setUsage(
                     VibrationAttributes.USAGE_RINGTONE).build();
 
-    @Rule public MockitoRule rule = MockitoJUnit.rule();
-    @Rule public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
+    @Rule
+    public FakeSettingsProviderRule mSettingsProviderRule = FakeSettingsProvider.rule();
 
-    @Mock private VibratorManagerService.NativeWrapper mNativeWrapperMock;
-    @Mock private PackageManagerInternal mPackageManagerInternalMock;
-    @Mock private PowerManagerInternal mPowerManagerInternalMock;
-    @Mock private PowerSaveState mPowerSaveStateMock;
-    @Mock private AppOpsManager mAppOpsManagerMock;
-    @Mock private IInputManager mIInputManagerMock;
+    @Mock
+    private VibratorManagerService.NativeWrapper mNativeWrapperMock;
+    @Mock
+    private PackageManagerInternal mPackageManagerInternalMock;
+    @Mock
+    private PowerManagerInternal mPowerManagerInternalMock;
+    @Mock
+    private PowerSaveState mPowerSaveStateMock;
+    @Mock
+    private AppOpsManager mAppOpsManagerMock;
+    @Mock
+    private IInputManager mIInputManagerMock;
 
     private final Map<Integer, FakeVibratorControllerProvider> mVibratorProviders = new HashMap<>();
 
@@ -398,6 +405,7 @@
     @Test
     public void registerVibratorStateListener_multipleVibratorsAreTriggered() throws Exception {
         mockVibrators(0, 1, 2);
+        mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
         VibratorManagerService service = createSystemReadyService();
         IVibratorStateListener[] listeners = new IVibratorStateListener[3];
         for (int i = 0; i < 3; i++) {
@@ -537,7 +545,7 @@
 
         setRingerMode(AudioManager.RINGER_MODE_NORMAL);
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
-        setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
+        setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
         VibratorManagerService service = createSystemReadyService();
         vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), RINGTONE_ATTRS);
         // Wait before checking it never played.
@@ -545,14 +553,14 @@
                 service, /* timeout= */ 50));
 
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
-        setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 1);
+        setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1);
         service = createSystemReadyService();
         vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK), RINGTONE_ATTRS);
         assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 1,
                 service, TEST_TIMEOUT_MILLIS));
 
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
-        setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
+        setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
         service = createSystemReadyService();
         vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK), RINGTONE_ATTRS);
         assertTrue(waitUntil(s -> fakeVibrator.getEffectSegments().size() == 2,
@@ -602,8 +610,8 @@
         VibrationEffect effect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
         AudioAttributes audioAttributes = new AudioAttributes.Builder()
                 .setUsage(AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY).build();
-        VibrationAttributes vibrationAttributes = new VibrationAttributes.Builder(
-                audioAttributes, effect).build();
+        VibrationAttributes vibrationAttributes =
+                new VibrationAttributes.Builder(audioAttributes).build();
 
         vibrate(service, effect, vibrationAttributes);
 
@@ -622,7 +630,7 @@
         vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
                 new VibrationAttributes.Builder().setUsage(
                         VibrationAttributes.USAGE_COMMUNICATION_REQUEST).build());
-        vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_TICK),
+        vibrate(service, VibrationEffect.createOneShot(2000, 200),
                 new VibrationAttributes.Builder().setUsage(
                         VibrationAttributes.USAGE_UNKNOWN).build());
 
@@ -636,13 +644,67 @@
         inOrderVerifier.verify(mAppOpsManagerMock).checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
                 eq(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION), anyInt(), anyString());
         inOrderVerifier.verify(mAppOpsManagerMock).checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
-                eq(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST),
+                eq(AudioAttributes.USAGE_VOICE_COMMUNICATION),
                 anyInt(), anyString());
         inOrderVerifier.verify(mAppOpsManagerMock).checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
                 eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString());
     }
 
     @Test
+    public void vibrate_withAttributesUnknownUsage_usesEffectToIdentifyTouchUsage() {
+        VibratorManagerService service = createSystemReadyService();
+
+        VibrationAttributes unknownAttributes = VibrationAttributes.createForUsage(
+                VibrationAttributes.USAGE_UNKNOWN);
+        vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK), unknownAttributes);
+        vibrate(service, VibrationEffect.createOneShot(200, 200), unknownAttributes);
+        vibrate(service, VibrationEffect.createWaveform(
+                new long[] { 100, 200, 300 }, new int[] {1, 2, 3}, -1), unknownAttributes);
+        vibrate(service,
+                VibrationEffect.startComposition()
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE)
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL)
+                        .compose(),
+                unknownAttributes);
+
+        verify(mAppOpsManagerMock, times(4))
+                .checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
+                        eq(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION), anyInt(), anyString());
+        verify(mAppOpsManagerMock, never())
+                .checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
+                        eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString());
+    }
+
+    @Test
+    public void vibrate_withAttributesUnknownUsage_ignoresEffectIfNotHapticFeedbackCandidate() {
+        VibratorManagerService service = createSystemReadyService();
+
+        VibrationAttributes unknownAttributes = VibrationAttributes.createForUsage(
+                VibrationAttributes.USAGE_UNKNOWN);
+        vibrate(service, VibrationEffect.get(VibrationEffect.RINGTONES[0]), unknownAttributes);
+        vibrate(service, VibrationEffect.createOneShot(2000, 200), unknownAttributes);
+        vibrate(service, VibrationEffect.createWaveform(
+                new long[] { 100, 200, 300 }, new int[] {1, 2, 3}, 0), unknownAttributes);
+        vibrate(service,
+                VibrationEffect.startComposition()
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_RISE)
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_QUICK_FALL)
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_SPIN)
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_THUD)
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+                        .compose(),
+                unknownAttributes);
+
+        verify(mAppOpsManagerMock, never())
+                .checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
+                        eq(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION), anyInt(), anyString());
+        verify(mAppOpsManagerMock, times(4))
+                .checkAudioOpNoThrow(eq(AppOpsManager.OP_VIBRATE),
+                        eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString());
+    }
+
+    @Test
     public void vibrate_withOngoingRepeatingVibration_ignoresEffect() throws Exception {
         mockVibrators(1);
         mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
@@ -658,8 +720,7 @@
                 service, TEST_TIMEOUT_MILLIS));
 
         vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
-                new VibrationAttributes.Builder().setUsage(
-                        VibrationAttributes.USAGE_TOUCH).build());
+                HAPTIC_FEEDBACK_ATTRS);
 
         // Wait before checking it never played a second effect.
         assertFalse(waitUntil(s -> mVibratorProviders.get(1).getEffectSegments().size() > 1,
@@ -682,8 +743,7 @@
                 service, TEST_TIMEOUT_MILLIS));
 
         vibrate(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
-                new VibrationAttributes.Builder().setUsage(
-                        VibrationAttributes.USAGE_TOUCH).build());
+                HAPTIC_FEEDBACK_ATTRS);
 
         // Wait before checking it never played a second effect.
         assertFalse(waitUntil(s -> mVibratorProviders.get(1).getEffectSegments().size() > 1,
@@ -1112,19 +1172,19 @@
 
         setRingerMode(AudioManager.RINGER_MODE_NORMAL);
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
-        setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
+        setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
         createSystemReadyService();
         int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
         assertEquals(IExternalVibratorService.SCALE_MUTE, scale);
 
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 0);
-        setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 1);
+        setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 1);
         createSystemReadyService();
         scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
         assertEquals(IExternalVibratorService.SCALE_NONE, scale);
 
         setUserSetting(Settings.System.VIBRATE_WHEN_RINGING, 1);
-        setGlobalSetting(Settings.Global.APPLY_RAMPING_RINGER, 0);
+        setUserSetting(Settings.System.APPLY_RAMPING_RINGER, 0);
         createSystemReadyService();
         scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
         assertEquals(IExternalVibratorService.SCALE_NONE, scale);
diff --git a/packages/overlays/OneHandedModeGesturalOverlay/Android.bp b/services/tests/servicestests/test-apps/StubApp/Android.bp
similarity index 73%
copy from packages/overlays/OneHandedModeGesturalOverlay/Android.bp
copy to services/tests/servicestests/test-apps/StubApp/Android.bp
index 468069d..99deb3f 100644
--- a/packages/overlays/OneHandedModeGesturalOverlay/Android.bp
+++ b/services/tests/servicestests/test-apps/StubApp/Android.bp
@@ -1,18 +1,16 @@
-//
-//  Copyright 2020, The Android Open Source Project
+// Copyright (C) 2021 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
+//      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 {
     // See: http://go/android-license-faq
@@ -23,8 +21,17 @@
     default_applicable_licenses: ["frameworks_base_license"],
 }
 
-runtime_resource_overlay {
-    name: "OneHandedModeGesturalOverlay",
-    theme: "OneHandedModeGestural",
-    product_specific: true,
+android_test_helper_app {
+    name: "StubTestApp",
+
+    sdk_version: "current",
+
+    srcs: ["**/*.java"],
+
+    dex_preopt: {
+        enabled: false,
+    },
+    optimize: {
+        enabled: false,
+    },
 }
diff --git a/services/tests/servicestests/test-apps/StubApp/AndroidManifest.xml b/services/tests/servicestests/test-apps/StubApp/AndroidManifest.xml
new file mode 100644
index 0000000..90172e7
--- /dev/null
+++ b/services/tests/servicestests/test-apps/StubApp/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2021 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.servicestests.apps.stubapp">
+
+    <application android:label="StubTestApp">
+        <activity android:name=".TestActivity"
+                  android:exported="true" />
+    </application>
+
+</manifest>
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt b/services/tests/servicestests/test-apps/StubApp/src/com/android/servicestests/apps/stubapp/TestActivity.java
similarity index 82%
copy from packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
copy to services/tests/servicestests/test-apps/StubApp/src/com/android/servicestests/apps/stubapp/TestActivity.java
index bacc66b..0d94676 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
+++ b/services/tests/servicestests/test-apps/StubApp/src/com/android/servicestests/apps/stubapp/TestActivity.java
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package com.android.systemui.flags
+package com.android.servicestests.apps.stubapp;
 
-interface FlagWriter {
-    fun setEnabled(key: Int, value: Boolean) {}
-}
\ No newline at end of file
+import android.app.Activity;
+
+public class TestActivity extends Activity {
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index d593e80..911fb6a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -422,7 +422,7 @@
 
     private void verifyNeverVibrate() {
         verify(mVibrator, never()).vibrate(anyInt(), anyString(), any(), anyString(),
-                any(AudioAttributes.class));
+                any(VibrationAttributes.class));
     }
 
     private void verifyVibrate() {
@@ -448,17 +448,18 @@
 
     private void verifyDelayedNeverVibrate() {
         verify(mVibrator, after(MAX_VIBRATION_DELAY).never()).vibrate(anyInt(), anyString(), any(),
-                anyString(), any(AudioAttributes.class));
+                anyString(), any(VibrationAttributes.class));
     }
 
     private void verifyVibrate(ArgumentMatcher<VibrationEffect> effectMatcher,
             VerificationMode verification) {
-        ArgumentCaptor<AudioAttributes> captor = ArgumentCaptor.forClass(AudioAttributes.class);
+        ArgumentCaptor<VibrationAttributes> captor =
+                ArgumentCaptor.forClass(VibrationAttributes.class);
         verify(mVibrator, verification).vibrate(eq(Process.SYSTEM_UID),
                 eq(PackageManagerService.PLATFORM_PACKAGE_NAME), argThat(effectMatcher),
                 anyString(), captor.capture());
-        assertEquals(0, (captor.getValue().getAllFlags()
-                & AudioAttributes.FLAG_BYPASS_INTERRUPTION_POLICY));
+        assertEquals(0, (captor.getValue().getFlags()
+                & VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY));
     }
 
     private void verifyStopVibrate() {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index fe36c1b..2f054b00 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -1363,6 +1363,66 @@
     }
 
     @Test
+    public void testSetComponentState() throws Exception {
+        Context context = mock(Context.class);
+        PackageManager pm = mock(PackageManager.class);
+        ApplicationInfo ai = new ApplicationInfo();
+        ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
+
+        when(context.getPackageName()).thenReturn(mContext.getPackageName());
+        when(context.getUserId()).thenReturn(mContext.getUserId());
+        when(context.getPackageManager()).thenReturn(pm);
+        when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
+
+        ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
+                APPROVAL_BY_COMPONENT);
+        ComponentName cn = ComponentName.unflattenFromString("a/a");
+
+        service.registerSystemService(cn, 0);
+        when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
+            Object[] args = invocation.getArguments();
+            ServiceConnection sc = (ServiceConnection) args[1];
+            sc.onServiceConnected(cn, mock(IBinder.class));
+            return true;
+        });
+
+        service.registerSystemService(cn, mZero.id);
+
+        service.setComponentState(cn, mZero.id, false);
+        verify(context).unbindService(any());
+    }
+
+    @Test
+    public void testSetComponentState_workProfile() throws Exception {
+        Context context = mock(Context.class);
+        PackageManager pm = mock(PackageManager.class);
+        ApplicationInfo ai = new ApplicationInfo();
+        ai.targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
+
+        when(context.getPackageName()).thenReturn(mContext.getPackageName());
+        when(context.getUserId()).thenReturn(mContext.getUserId());
+        when(context.getPackageManager()).thenReturn(pm);
+        when(pm.getApplicationInfo(anyString(), anyInt())).thenReturn(ai);
+
+        ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles, mIpm,
+                APPROVAL_BY_COMPONENT);
+        ComponentName cn = ComponentName.unflattenFromString("a/a");
+
+        service.registerSystemService(cn, 0);
+        when(context.bindServiceAsUser(any(), any(), anyInt(), any())).thenAnswer(invocation -> {
+            Object[] args = invocation.getArguments();
+            ServiceConnection sc = (ServiceConnection) args[1];
+            sc.onServiceConnected(cn, mock(IBinder.class));
+            return true;
+        });
+
+        service.registerSystemService(cn, mZero.id);
+
+        service.setComponentState(cn, mTen.id, false);
+        verify(context, never()).unbindService(any());
+    }
+
+    @Test
     public void testOnPackagesChanged_nullValuesPassed_noNullPointers() {
         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index bc44ab0..837850f 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -99,6 +99,9 @@
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
+import static java.util.Collections.emptyList;
+import static java.util.Collections.singletonList;
+
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.AlarmManager;
@@ -119,6 +122,7 @@
 import android.app.StatsManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.app.usage.UsageStatsManagerInternal;
+import android.companion.AssociationInfo;
 import android.companion.ICompanionDeviceManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -2335,10 +2339,8 @@
 
     @Test
     public void testCreateChannelNotifyListener() throws Exception {
-        List<String> associations = new ArrayList<>();
-        associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
         mService.setPreferencesHelper(mPreferencesHelper);
         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
@@ -2364,10 +2366,8 @@
 
     @Test
     public void testCreateChannelGroupNotifyListener() throws Exception {
-        List<String> associations = new ArrayList<>();
-        associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
         mService.setPreferencesHelper(mPreferencesHelper);
         NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
         NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
@@ -2385,10 +2385,8 @@
 
     @Test
     public void testUpdateChannelNotifyListener() throws Exception {
-        List<String> associations = new ArrayList<>();
-        associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
         mService.setPreferencesHelper(mPreferencesHelper);
         mTestNotificationChannel.setLightColor(Color.CYAN);
         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
@@ -2404,10 +2402,8 @@
 
     @Test
     public void testDeleteChannelNotifyListener() throws Exception {
-        List<String> associations = new ArrayList<>();
-        associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
         mService.setPreferencesHelper(mPreferencesHelper);
         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
@@ -2423,10 +2419,8 @@
 
     @Test
     public void testDeleteChannelOnlyDoExtraWorkIfExisted() throws Exception {
-        List<String> associations = new ArrayList<>();
-        associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
         mService.setPreferencesHelper(mPreferencesHelper);
         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
@@ -2439,10 +2433,8 @@
 
     @Test
     public void testDeleteChannelGroupNotifyListener() throws Exception {
-        List<String> associations = new ArrayList<>();
-        associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
         NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
         mService.setPreferencesHelper(mPreferencesHelper);
         when(mPreferencesHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
@@ -2457,10 +2449,8 @@
     @Test
     public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
-        List<String> associations = new ArrayList<>();
-        associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
         when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
                 .thenReturn(mTestNotificationChannel);
@@ -2479,9 +2469,8 @@
     @Test
     public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
-        List<String> associations = new ArrayList<>();
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(emptyList());
 
         try {
             mBinderService.updateNotificationChannelFromPrivilegedListener(
@@ -2502,10 +2491,8 @@
     @Test
     public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
-        List<String> associations = new ArrayList<>();
-        associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
         mListener = mock(ManagedServices.ManagedServiceInfo.class);
         mListener.component = new ComponentName(PKG, PKG);
         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
@@ -2530,10 +2517,8 @@
     @Test
     public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
-        List<String> associations = new ArrayList<>();
-        associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
 
         mBinderService.getNotificationChannelsFromPrivilegedListener(
                 null, PKG, Process.myUserHandle());
@@ -2545,9 +2530,8 @@
     @Test
     public void testGetNotificationChannelFromPrivilegedListener_cdm_noAccess() throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
-        List<String> associations = new ArrayList<>();
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(emptyList());
 
         try {
             mBinderService.getNotificationChannelsFromPrivilegedListener(
@@ -2566,7 +2550,7 @@
             throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(new ArrayList<>());
+                .thenReturn(emptyList());
         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(true);
 
         mBinderService.getNotificationChannelsFromPrivilegedListener(
@@ -2581,7 +2565,7 @@
             throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(new ArrayList<>());
+                .thenReturn(emptyList());
         when(mAssistants.isServiceTokenValidLocked(any())).thenReturn(false);
 
         try {
@@ -2599,10 +2583,8 @@
     @Test
     public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
-        List<String> associations = new ArrayList<>();
-        associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
         mListener = mock(ManagedServices.ManagedServiceInfo.class);
         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
@@ -2622,10 +2604,8 @@
     @Test
     public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
-        List<String> associations = new ArrayList<>();
-        associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
 
         mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
                 null, PKG, Process.myUserHandle());
@@ -2636,9 +2616,8 @@
     @Test
     public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
-        List<String> associations = new ArrayList<>();
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(emptyList());
 
         try {
             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
@@ -2654,9 +2633,8 @@
     @Test
     public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
         mService.setPreferencesHelper(mPreferencesHelper);
-        List<String> associations = new ArrayList<>();
         when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
-                .thenReturn(associations);
+                .thenReturn(emptyList());
         mListener = mock(ManagedServices.ManagedServiceInfo.class);
         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
         when(mListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
@@ -3859,6 +3837,19 @@
     }
 
     @Test
+    public void testTextChangedSet_forNewNotifs() throws Exception {
+        NotificationRecord original = generateNotificationRecord(mTestNotificationChannel);
+        mService.addEnqueuedNotification(original);
+
+        NotificationManagerService.PostNotificationRunnable runnable =
+                mService.new PostNotificationRunnable(original.getKey());
+        runnable.run();
+        waitForIdle();
+
+        assertTrue(original.isTextChanged());
+    }
+
+    @Test
     public void testVisuallyInterruptive_notSeen() throws Exception {
         NotificationRecord original = generateNotificationRecord(mTestNotificationChannel);
         mService.addNotification(original);
@@ -7313,12 +7304,12 @@
 
         // Make sure the shortcut is cached.
         verify(mShortcutServiceInternal).cacheShortcuts(
-                anyInt(), any(), eq(PKG), eq(Collections.singletonList(VALID_CONVO_SHORTCUT_ID)),
+                anyInt(), any(), eq(PKG), eq(singletonList(VALID_CONVO_SHORTCUT_ID)),
                 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
 
         // Test: Remove the shortcut
         when(mLauncherApps.getShortcuts(any(), any())).thenReturn(null);
-        launcherAppsCallback.getValue().onShortcutsChanged(PKG, Collections.emptyList(),
+        launcherAppsCallback.getValue().onShortcutsChanged(PKG, emptyList(),
                 UserHandle.getUserHandleForUid(mUid));
         waitForIdle();
 
@@ -7386,7 +7377,7 @@
 
         // Make sure the shortcut is cached.
         verify(mShortcutServiceInternal).cacheShortcuts(
-                anyInt(), any(), eq(PKG), eq(Collections.singletonList(shortcutId)),
+                anyInt(), any(), eq(PKG), eq(singletonList(shortcutId)),
                 eq(USER_SYSTEM), eq(ShortcutInfo.FLAG_CACHED_NOTIFICATIONS));
 
         // Test: Remove the notification
@@ -8498,6 +8489,18 @@
         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
                 r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse();
 
+        // using the style, but incorrect type in session - blocked
+        nb.setStyle(new Notification.MediaStyle());
+        Bundle extras = new Bundle();
+        extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, new Intent());
+        nb.addExtras(extras);
+        sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
+                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
+        r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+        assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
+                r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse();
+
         // style + media session - bypasses block
         nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
index d6ca24e..2e5cf3c 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationPermissionMigrationTest.java
@@ -90,6 +90,7 @@
 import android.media.session.MediaSession;
 import android.os.Binder;
 import android.os.Build;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Process;
@@ -747,6 +748,18 @@
         assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
                 r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse();
 
+        // using the style, but incorrect type in session - blocked
+        nb.setStyle(new Notification.MediaStyle());
+        Bundle extras = new Bundle();
+        extras.putParcelable(Notification.EXTRA_MEDIA_SESSION, new Intent());
+        nb.addExtras(extras);
+        sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
+                nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0);
+        r = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+
+        assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(),
+                r.getSbn().getId(), r.getSbn().getTag(), r, false)).isFalse();
+
         // style + media session - bypasses block
         nb.setStyle(new Notification.MediaStyle().setMediaSession(mock(MediaSession.Token.class)));
         sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0,
diff --git a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
index 1ff67240..00bc546 100644
--- a/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/SingleKeyGestureTests.java
@@ -150,11 +150,12 @@
 
     }
 
-    private void pressKey(long eventTime, int keyCode, long pressTime) {
-        pressKey(eventTime, keyCode, pressTime, true /* interactive */);
+    private void pressKey(int keyCode, long pressTime) {
+        pressKey(keyCode, pressTime, true /* interactive */);
     }
 
-    private void pressKey(long eventTime, int keyCode, long pressTime, boolean interactive) {
+    private void pressKey(int keyCode, long pressTime, boolean interactive) {
+        long eventTime = SystemClock.uptimeMillis();
         final KeyEvent keyDown = new KeyEvent(eventTime, eventTime, ACTION_DOWN,
                 keyCode, 0 /* repeat */, 0 /* metaState */);
         mDetector.interceptKey(keyDown, interactive);
@@ -175,54 +176,48 @@
 
     @Test
     public void testShortPress() throws InterruptedException {
-        final long eventTime = SystemClock.uptimeMillis();
-        pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
+        pressKey(KEYCODE_POWER, 0 /* pressTime */);
         assertTrue(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
     }
 
     @Test
     public void testLongPress() throws InterruptedException {
-        final long eventTime = SystemClock.uptimeMillis();
-        pressKey(eventTime, KEYCODE_POWER, mLongPressTime);
+        pressKey(KEYCODE_POWER, mLongPressTime);
         assertTrue(mLongPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
     }
 
     @Test
     public void testVeryLongPress() throws InterruptedException {
-        final long eventTime = SystemClock.uptimeMillis();
-        pressKey(eventTime, KEYCODE_POWER, mVeryLongPressTime);
+        pressKey(KEYCODE_POWER, mVeryLongPressTime);
         assertTrue(mVeryLongPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
     }
 
     @Test
     public void testMultiPress() throws InterruptedException {
-        final long eventTime = SystemClock.uptimeMillis();
         // Double presses.
         mExpectedMultiPressCount = 2;
-        pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
-        pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
+        pressKey(KEYCODE_POWER, 0 /* pressTime */);
+        pressKey(KEYCODE_POWER, 0 /* pressTime */);
         assertTrue(mMultiPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
 
         // Triple presses.
         mExpectedMultiPressCount = 3;
         mMultiPressed = new CountDownLatch(1);
-        pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
-        pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
-        pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
+        pressKey(KEYCODE_POWER, 0 /* pressTime */);
+        pressKey(KEYCODE_POWER, 0 /* pressTime */);
+        pressKey(KEYCODE_POWER, 0 /* pressTime */);
         assertTrue(mMultiPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
     }
 
     @Test
     public void testNonInteractive() throws InterruptedException {
-        long eventTime = SystemClock.uptimeMillis();
         // Disallow short press behavior from non interactive.
         mAllowNonInteractiveForPress = false;
-        pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */, false /* interactive */);
+        pressKey(KEYCODE_POWER, 0 /* pressTime */, false /* interactive */);
         assertFalse(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
 
         // Allow long press behavior from non interactive.
-        eventTime = SystemClock.uptimeMillis();
-        pressKey(eventTime, KEYCODE_POWER, mLongPressTime, false /* interactive */);
+        pressKey(KEYCODE_POWER, mLongPressTime, false /* interactive */);
         assertTrue(mLongPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
     }
 
@@ -238,9 +233,8 @@
             for (int i = 0; i < 100; i++) {
                 mShortPressed = new CountDownLatch(2);
                 newHandler.runWithScissors(() -> {
-                    final long eventTime = SystemClock.uptimeMillis();
-                    pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
-                    pressKey(eventTime, KEYCODE_BACK, 0 /* pressTime */);
+                    pressKey(KEYCODE_POWER, 0 /* pressTime */);
+                    pressKey(KEYCODE_BACK, 0 /* pressTime */);
                 }, mWaitTimeout);
                 assertTrue(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
             }
@@ -261,15 +255,13 @@
                 mMultiPressed = new CountDownLatch(1);
                 mShortPressed = new CountDownLatch(1);
                 newHandler.runWithScissors(() -> {
-                    final long eventTime = SystemClock.uptimeMillis();
-                    pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
-                    pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
+                    pressKey(KEYCODE_POWER, 0 /* pressTime */);
+                    pressKey(KEYCODE_POWER, 0 /* pressTime */);
                 }, mWaitTimeout);
                 assertTrue(mMultiPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
 
                 newHandler.runWithScissors(() -> {
-                    final long eventTime = SystemClock.uptimeMillis();
-                    pressKey(eventTime, KEYCODE_POWER, 0 /* pressTime */);
+                    pressKey(KEYCODE_POWER, 0 /* pressTime */);
                 }, mWaitTimeout);
                 assertTrue(mShortPressed.await(mWaitTimeout, TimeUnit.MILLISECONDS));
             }
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index bc0cc1f..7a133ea 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1389,7 +1389,8 @@
         final Task task = activity.getTask();
         // Make keyguard locked and set the top activity show-when-locked.
         KeyguardController keyguardController = activity.mTaskSupervisor.getKeyguardController();
-        doReturn(true).when(keyguardController).isKeyguardLocked();
+        int displayId = activity.getDisplayId();
+        doReturn(true).when(keyguardController).isKeyguardLocked(eq(displayId));
         final ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(task).build();
         topActivity.mVisibleRequested = true;
         topActivity.nowVisible = true;
@@ -1777,11 +1778,6 @@
                 anyInt() /* orientation */, anyInt() /* lastRotation */);
         // Set to visible so the activity can freeze the screen.
         activity.setVisibility(true);
-        // Update the display policy to make the screen fully turned on so the freeze is allowed
-        display.getDisplayPolicy().screenTurnedOn(null);
-        display.getDisplayPolicy().finishKeyguardDrawn();
-        display.getDisplayPolicy().finishWindowsDrawn();
-        display.getDisplayPolicy().finishScreenTurningOn();
 
         display.rotateInDifferentOrientationIfNeeded(activity);
         display.setFixedRotationLaunchingAppUnchecked(activity);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index abd43a4..afc2b87 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -39,6 +39,7 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.times;
@@ -246,7 +247,7 @@
         doReturn(true).when(record)
                 .checkEnterPictureInPictureState("enterPictureInPictureMode", false);
         doReturn(false).when(record).inPinnedWindowingMode();
-        doReturn(false).when(mAtm).isKeyguardLocked();
+        doReturn(false).when(mAtm).isKeyguardLocked(anyInt());
 
         //to simulate NPE
         doReturn(null).when(record).getParent();
@@ -853,12 +854,19 @@
         ActivityTaskManagerInternal.PackageConfigurationUpdater packageConfigUpdater =
                 mAtm.mInternal.createPackageConfigurationUpdater(DEFAULT_PACKAGE_NAME,
                         DEFAULT_USER_ID);
+
+        // committing empty locales, when no config is set should return false.
+        assertFalse(packageConfigUpdater.setLocales(LocaleList.getEmptyLocaleList()).commit());
+
         // committing new configuration returns true;
         assertTrue(packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
                 .commit());
         // applying the same configuration returns false.
         assertFalse(packageConfigUpdater.setLocales(LocaleList.forLanguageTags("en-XA,ar-XB"))
                 .commit());
+
+        // committing empty locales and undefined nightMode should return true (deletes the
+        // pre-existing record) if some config was previously set.
         assertTrue(packageConfigUpdater.setLocales(LocaleList.getEmptyLocaleList())
                 .setNightMode(Configuration.UI_MODE_NIGHT_UNDEFINED).commit());
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
index 5d0e34a..5062706 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -334,6 +334,18 @@
     }
 
     @Test
+    public void testExitAnimationDone_beforeAppTransition() {
+        final Task task = createTask(mDisplayContent);
+        final WindowState win = createAppWindow(task, ACTIVITY_TYPE_STANDARD, "Win");
+        spyOn(win);
+        win.mAnimatingExit = true;
+        mDisplayContent.mAppTransition.setTimeout();
+        mDisplayContent.mAppTransitionController.handleAppTransitionReady();
+
+        verify(win).onExitAnimationDone();
+    }
+
+    @Test
     public void testGetAnimationTargets_windowsAreBeingReplaced() {
         // [DisplayContent] -+- [Task1] - [ActivityRecord1] (opening, visible)
         //                                       +- [AppWindow1] (being-replaced)
@@ -803,6 +815,7 @@
         final TaskFragment taskFragment = createTaskFragmentWithEmbeddedActivity(task, organizer);
         final ActivityRecord openingActivity = taskFragment.getTopMostActivity();
         openingActivity.allDrawn = true;
+        task.effectiveUid = openingActivity.getUid();
         spyOn(mDisplayContent.mAppTransition);
 
         // Prepare a transition.
@@ -879,6 +892,7 @@
         final ActivityRecord closingActivity = taskFragment.getTopMostActivity();
         closingActivity.allDrawn = true;
         closingActivity.info.applicationInfo.uid = 12345;
+        task.effectiveUid = closingActivity.getUid();
         // Opening non-embedded activity with different UID.
         final ActivityRecord openingActivity = createActivityRecord(task);
         openingActivity.info.applicationInfo.uid = 54321;
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 046328d..d7a0ab3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -102,6 +102,7 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.when;
 
 import android.app.ActivityTaskManager;
 import android.app.WindowConfiguration;
@@ -134,6 +135,7 @@
 import android.view.SurfaceControl.Transaction;
 import android.view.View;
 import android.view.WindowManager;
+import android.window.IDisplayAreaOrganizer;
 import android.window.WindowContainerToken;
 
 import androidx.test.filters.SmallTest;
@@ -390,6 +392,32 @@
         assertNull("computeImeParent() should be null", mDisplayContent.computeImeParent());
     }
 
+    @Test
+    public void testUpdateImeParent_skipForOrganizedImeContainer() {
+        final DisplayArea.Tokens imeContainer = mDisplayContent.getImeContainer();
+        final ActivityRecord activity = createActivityRecord(mDisplayContent);
+
+        final WindowState startingWin = createWindow(null, TYPE_APPLICATION_STARTING, activity,
+                "startingWin");
+        startingWin.setHasSurface(true);
+        assertTrue(startingWin.canBeImeTarget());
+        final SurfaceControl imeSurfaceParent = mock(SurfaceControl.class);
+        doReturn(imeSurfaceParent).when(mDisplayContent).computeImeParent();
+
+        // Main precondition for this test: organize the ImeContainer.
+        final IDisplayAreaOrganizer mockImeOrganizer = mock(IDisplayAreaOrganizer.class);
+        when(mockImeOrganizer.asBinder()).thenReturn(new Binder());
+        imeContainer.setOrganizer(mockImeOrganizer);
+
+        mDisplayContent.updateImeParent();
+
+        assertNull("Don't reparent the surface of an organized ImeContainer.",
+                mDisplayContent.mInputMethodSurfaceParent);
+
+        // Clean up organizer.
+        imeContainer.setOrganizer(null);
+    }
+
     /**
      * This tests root task movement between displays and proper root task's, task's and app token's
      * display container references updates.
@@ -653,7 +681,7 @@
 
         final int maxWidth = 300;
         final int resultingHeight = (maxWidth * baseHeight) / baseWidth;
-        final int resultingDensity = baseDensity;
+        final int resultingDensity = (baseDensity * maxWidth) / baseWidth;
 
         displayContent.setMaxUiWidth(maxWidth);
         verifySizes(displayContent, maxWidth, resultingHeight, resultingDensity);
@@ -728,6 +756,33 @@
     }
 
     @Test
+    public void testSetForcedDensity() {
+        final DisplayContent displayContent = createDisplayNoUpdateDisplayInfo();
+        final int baseWidth = 1280;
+        final int baseHeight = 720;
+        final int baseDensity = 320;
+
+        displayContent.mInitialDisplayWidth = baseWidth;
+        displayContent.mInitialDisplayHeight = baseHeight;
+        displayContent.mInitialDisplayDensity = baseDensity;
+        displayContent.updateBaseDisplayMetrics(baseWidth, baseHeight, baseDensity);
+
+        final int forcedDensity = 600;
+
+        // Verify that forcing the density is honored and the size doesn't change.
+        displayContent.setForcedDensity(forcedDensity, 0 /* userId */);
+        verifySizes(displayContent, baseWidth, baseHeight, forcedDensity);
+
+        // Verify that forcing the density is idempotent.
+        displayContent.setForcedDensity(forcedDensity, 0 /* userId */);
+        verifySizes(displayContent, baseWidth, baseHeight, forcedDensity);
+
+        // Verify that forcing resolution won't affect the already forced density.
+        displayContent.setForcedSize(1800, 1200);
+        verifySizes(displayContent, 1800, 1200, forcedDensity);
+    }
+
+    @Test
     public void testDisplayCutout_rot0() {
         final DisplayContent dc = createNewDisplay();
         dc.mInitialDisplayWidth = 200;
@@ -827,12 +882,12 @@
                 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
 
         keyguard.mAttrs.screenOrientation = SCREEN_ORIENTATION_PORTRAIT;
-        mAtm.mKeyguardController.setKeyguardShown(true /* keyguardShowing */,
+        mAtm.mKeyguardController.setKeyguardShown(window.getDisplayId(), true /* keyguardShowing */,
                 false /* aodShowing */);
         assertEquals("Visible keyguard must influence device orientation",
                 SCREEN_ORIENTATION_PORTRAIT, dc.getOrientation());
 
-        mAtm.mKeyguardController.keyguardGoingAway(0 /* flags */);
+        mAtm.mKeyguardController.keyguardGoingAway(window.getDisplayId(), 0 /* flags */);
         assertEquals("Keyguard that is going away must not influence device orientation",
                 SCREEN_ORIENTATION_LANDSCAPE, dc.getOrientation());
     }
@@ -2137,7 +2192,7 @@
         assertTopRunningActivity(activity, display);
 
         // Check to make sure activity not reported when it cannot show on lock and lock is on.
-        doReturn(true).when(keyguard).isKeyguardLocked();
+        doReturn(true).when(keyguard).isKeyguardLocked(anyInt());
         assertEquals(activity, display.topRunningActivity());
         assertNull(display.topRunningActivity(true /* considerKeyguardState */));
 
@@ -2175,11 +2230,11 @@
         final WindowState appWin = createWindow(null, TYPE_APPLICATION, mDisplayContent, "appWin");
         final ActivityRecord activity = appWin.mActivityRecord;
 
-        mAtm.mKeyguardController.setKeyguardShown(true /* keyguardShowing */,
+        mAtm.mKeyguardController.setKeyguardShown(appWin.getDisplayId(), true /* keyguardShowing */,
                 true /* aodShowing */);
         assertFalse(activity.isVisibleRequested());
 
-        mAtm.mKeyguardController.keyguardGoingAway(0 /* flags */);
+        mAtm.mKeyguardController.keyguardGoingAway(appWin.getDisplayId(), 0 /* flags */);
         assertTrue(activity.isVisibleRequested());
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index 70aa2a2..8da8596 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.wm;
 
+import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_IME;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
@@ -251,28 +252,38 @@
 
     @Test
     public void testOverlappingWithNavBar() {
+        final InsetsSource navSource = new InsetsSource(ITYPE_NAVIGATION_BAR);
+        navSource.setFrame(new Rect(100, 200, 200, 300));
+        testOverlappingWithNavBarType(navSource);
+    }
+
+    @Test
+    public void testOverlappingWithExtraNavBar() {
+        final InsetsSource navSource = new InsetsSource(ITYPE_EXTRA_NAVIGATION_BAR);
+        navSource.setFrame(new Rect(100, 200, 200, 300));
+        testOverlappingWithNavBarType(navSource);
+    }
+
+    private void testOverlappingWithNavBarType(InsetsSource navSource) {
         final WindowState targetWin = createApplicationWindow();
         final WindowFrames winFrame = targetWin.getWindowFrames();
         winFrame.mFrame.set(new Rect(100, 100, 200, 200));
-
-        final WindowState navigationBar = createNavigationBarWindow();
-
-        navigationBar.getFrame().set(new Rect(100, 200, 200, 300));
+        targetWin.mAboveInsetsState.addSource(navSource);
 
         assertFalse("Freeform is overlapping with navigation bar",
-                DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+                DisplayPolicy.isOverlappingWithNavBar(targetWin));
 
         winFrame.mFrame.set(new Rect(100, 101, 200, 201));
         assertTrue("Freeform should be overlapping with navigation bar (bottom)",
-                DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+                DisplayPolicy.isOverlappingWithNavBar(targetWin));
 
         winFrame.mFrame.set(new Rect(99, 200, 199, 300));
         assertTrue("Freeform should be overlapping with navigation bar (right)",
-                DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+                DisplayPolicy.isOverlappingWithNavBar(targetWin));
 
         winFrame.mFrame.set(new Rect(199, 200, 299, 300));
         assertTrue("Freeform should be overlapping with navigation bar (left)",
-                DisplayPolicy.isOverlappingWithNavBar(targetWin, navigationBar));
+                DisplayPolicy.isOverlappingWithNavBar(targetWin));
     }
 
     private WindowState createNavigationBarWindow() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
index 4509ff4..dbb7fae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
@@ -41,14 +41,17 @@
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
 import android.platform.test.annotations.Presubmit;
 import android.view.Display;
+import android.window.IDisplayAreaOrganizer;
 
 import androidx.test.filters.SmallTest;
 
@@ -346,6 +349,39 @@
     }
 
     @Test
+    public void testPlaceImeContainer_skipReparentForOrganizedImeContainer() {
+        setupImeWindow();
+        final DisplayArea.Tokens imeContainer = mDisplay.getImeContainer();
+        final WindowToken imeToken = tokenOfType(TYPE_INPUT_METHOD);
+
+        // By default, the ime container is attached to DC as defined in DAPolicy.
+        assertThat(imeContainer.getRootDisplayArea()).isEqualTo(mDisplay);
+        assertThat(mDisplay.findAreaForTokenInLayer(imeToken)).isEqualTo(imeContainer);
+
+        final WindowState firstActivityWin =
+                createWindow(null /* parent */, TYPE_APPLICATION_STARTING, mFirstActivity,
+                        "firstActivityWin");
+        spyOn(firstActivityWin);
+        // firstActivityWin should be the target
+        doReturn(true).when(firstActivityWin).canBeImeTarget();
+
+        // Main precondition for this test: organize the ImeContainer.
+        final IDisplayAreaOrganizer mockImeOrganizer = mock(IDisplayAreaOrganizer.class);
+        when(mockImeOrganizer.asBinder()).thenReturn(new Binder());
+        imeContainer.setOrganizer(mockImeOrganizer);
+
+        WindowState imeTarget = mDisplay.computeImeTarget(true /* updateImeTarget */);
+
+        // The IME target must be updated but the don't reparent organized ImeContainers.
+        // See DisplayAreaOrganizer#FEATURE_IME.
+        assertThat(imeTarget).isEqualTo(firstActivityWin);
+        verify(mFirstRoot, never()).placeImeContainer(imeContainer);
+
+        // Clean up organizer.
+        imeContainer.setOrganizer(null);
+    }
+
+    @Test
     public void testResizableFixedOrientationApp_fixedOrientationLetterboxing() {
         mFirstRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
         mSecondRoot.setIgnoreOrientationRequest(false /* ignoreOrientationRequest */);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java
index a8ede13..407f9cf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.STATE_ON;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
@@ -29,7 +30,9 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
 
+import android.app.ActivityThread;
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Rect;
@@ -44,6 +47,7 @@
 import com.android.server.inputmethod.InputMethodManagerService;
 import com.android.server.inputmethod.InputMethodMenuController;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -62,18 +66,24 @@
     private InputMethodMenuController mController;
     private DualDisplayAreaGroupPolicyTest.DualDisplayContent mSecondaryDisplay;
 
+    private IWindowManager mIWindowManager;
+    private DisplayManagerGlobal mDisplayManagerGlobal;
+
     @Before
     public void setUp() throws Exception {
-        // Let the Display to be created with the DualDisplay policy.
+        // Let the Display be created with the DualDisplay policy.
         final DisplayAreaPolicy.Provider policyProvider =
                 new DualDisplayAreaGroupPolicyTest.DualDisplayTestPolicyProvider();
         Mockito.doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider();
 
         mController = new InputMethodMenuController(mock(InputMethodManagerService.class));
+        mSecondaryDisplay = new DualDisplayAreaGroupPolicyTest.DualDisplayContent
+                .Builder(mAtm, 1000, 1000).build();
+        mSecondaryDisplay.getDisplayInfo().state = STATE_ON;
 
         // Mock addWindowTokenWithOptions to create a test window token.
-        IWindowManager wms = WindowManagerGlobal.getWindowManagerService();
-        spyOn(wms);
+        mIWindowManager = WindowManagerGlobal.getWindowManagerService();
+        spyOn(mIWindowManager);
         doAnswer(invocation -> {
             Object[] args = invocation.getArguments();
             IBinder clientToken = (IBinder) args[0];
@@ -83,19 +93,24 @@
                     dc.getImeContainer(), 1000 /* ownerUid */, TYPE_INPUT_METHOD_DIALOG,
                     null /* options */);
             return dc.getImeContainer().getConfiguration();
-        }).when(wms).attachWindowContextToDisplayArea(any(), eq(TYPE_INPUT_METHOD_DIALOG),
-                anyInt(), any());
-
-        mSecondaryDisplay = new DualDisplayAreaGroupPolicyTest.DualDisplayContent
-                .Builder(mAtm, 1000, 1000).build();
-
-        // Mock DisplayManagerGlobal to return test display when obtaining Display instance.
+        }).when(mIWindowManager).attachWindowContextToDisplayArea(any(),
+                eq(TYPE_INPUT_METHOD_DIALOG), anyInt(), any());
+        mDisplayManagerGlobal = DisplayManagerGlobal.getInstance();
+        spyOn(mDisplayManagerGlobal);
         final int displayId = mSecondaryDisplay.getDisplayId();
         final Display display = mSecondaryDisplay.getDisplay();
-        DisplayManagerGlobal displayManagerGlobal = DisplayManagerGlobal.getInstance();
-        spyOn(displayManagerGlobal);
-        doReturn(display).when(displayManagerGlobal).getCompatibleDisplay(eq(displayId),
+        doReturn(display).when(mDisplayManagerGlobal).getCompatibleDisplay(eq(displayId),
                 (Resources) any());
+        Context systemUiContext = ActivityThread.currentActivityThread()
+                .getSystemUiContext(displayId);
+        spyOn(systemUiContext);
+        doReturn(display).when(systemUiContext).getDisplay();
+    }
+
+    @After
+    public void tearDown() {
+        reset(mIWindowManager);
+        reset(mDisplayManagerGlobal);
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
index 030733b..bb49cd2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
@@ -29,6 +29,7 @@
 import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
+import static android.view.Display.DEFAULT_DISPLAY;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -1505,7 +1506,7 @@
         final UnknownAppVisibilityController unknownAppVisibilityController =
                 mDefaultTaskDisplayArea.mDisplayContent.mUnknownAppVisibilityController;
         final KeyguardController keyguardController = mSupervisor.getKeyguardController();
-        doReturn(true).when(keyguardController).isKeyguardLocked();
+        doReturn(true).when(keyguardController).isKeyguardLocked(eq(DEFAULT_DISPLAY));
 
         // Start 2 activities that their processes have not yet started.
         final ActivityRecord[] activities = new ActivityRecord[2];
@@ -1571,7 +1572,7 @@
         display.isDefaultDisplay = isDefaultDisplay;
 
         task.mDisplayContent = display;
-        doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway();
+        doReturn(keyguardGoingAway).when(display).isKeyguardGoingAway();
         doReturn(displaySleeping).when(display).isSleeping();
         doReturn(focusedRootTask).when(task).isFocusedRootTaskOnDisplay();
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
index d89d64a..a5c6dc0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java
@@ -21,6 +21,7 @@
 import static com.android.server.wm.testing.Assert.assertThrows;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
@@ -352,28 +353,66 @@
     }
 
     @Test
-    public void testApplyTransaction_enforceHierarchyChange_createTaskFragment() {
+    public void testApplyTransaction_enforceHierarchyChange_createTaskFragment()
+            throws RemoteException {
+        mController.registerOrganizer(mIOrganizer);
+        final ActivityRecord activity = createActivityRecord(mDisplayContent);
+        final int uid = Binder.getCallingUid();
+        activity.info.applicationInfo.uid = uid;
+        activity.getTask().effectiveUid = uid;
+        final IBinder fragmentToken = new Binder();
+        final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
+                mOrganizerToken, fragmentToken, activity.token).build();
         mOrganizer.applyTransaction(mTransaction);
 
         // Allow organizer to create TaskFragment and start/reparent activity to TaskFragment.
-        final TaskFragmentCreationParams mockParams = mock(TaskFragmentCreationParams.class);
-        doReturn(mOrganizerToken).when(mockParams).getOrganizer();
-        mTransaction.createTaskFragment(mockParams);
+        mTransaction.createTaskFragment(params);
         mTransaction.startActivityInTaskFragment(
                 mFragmentToken, null /* callerToken */, new Intent(), null /* activityOptions */);
         mTransaction.reparentActivityToTaskFragment(mFragmentToken, mock(IBinder.class));
         mTransaction.setAdjacentTaskFragments(mFragmentToken, mock(IBinder.class),
                 null /* options */);
+        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
 
-        // It is expected to fail for the mock TaskFragmentCreationParams. It is ok as we are
-        // testing the security check here.
-        assertThrows(IllegalArgumentException.class, () -> {
-            try {
-                mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
-            } catch (RemoteException e) {
-                fail();
-            }
-        });
+        // Successfully created a TaskFragment.
+        final TaskFragment taskFragment = mAtm.mWindowOrganizerController
+                .getTaskFragment(fragmentToken);
+        assertNotNull(taskFragment);
+        assertEquals(activity.getTask(), taskFragment.getTask());
+    }
+
+    @Test
+    public void testApplyTransaction_createTaskFragment_failForDifferentUid()
+            throws RemoteException {
+        mController.registerOrganizer(mIOrganizer);
+        final ActivityRecord activity = createActivityRecord(mDisplayContent);
+        final int uid = Binder.getCallingUid();
+        final IBinder fragmentToken = new Binder();
+        final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder(
+                mOrganizerToken, fragmentToken, activity.token).build();
+        mOrganizer.applyTransaction(mTransaction);
+        mTransaction.createTaskFragment(params);
+
+        // Fail to create TaskFragment when the task uid is different from caller.
+        activity.info.applicationInfo.uid = uid;
+        activity.getTask().effectiveUid = uid + 1;
+        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+
+        assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+
+        // Fail to create TaskFragment when the task uid is different from owner activity.
+        activity.info.applicationInfo.uid = uid + 1;
+        activity.getTask().effectiveUid = uid;
+        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+
+        assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
+
+        // Successfully created a TaskFragment for same uid.
+        activity.info.applicationInfo.uid = uid;
+        activity.getTask().effectiveUid = uid;
+        mAtm.getWindowOrganizerController().applyTransaction(mTransaction);
+
+        assertNotNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken));
     }
 
     @Test
@@ -424,4 +463,26 @@
 
         verify(mAtm.mRootWindowContainer).resumeFocusedTasksTopActivities();
     }
+
+    @Test
+    public void testDeferPendingTaskFragmentEventsOfInvisibleTask() {
+        // Task - TaskFragment - Activity.
+        final Task task = createTask(mDisplayContent);
+        final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
+                .setParentTask(task)
+                .setOrganizer(mOrganizer)
+                .build();
+
+        // Mock the task to invisible
+        doReturn(false).when(task).shouldBeVisible(any());
+
+        // Sending events
+        mController.registerOrganizer(mIOrganizer);
+        taskFragment.mTaskFragmentAppearedSent = true;
+        mController.onTaskFragmentInfoChanged(mIOrganizer, taskFragment);
+        mController.dispatchPendingEvents();
+
+        // Verifies that event was not sent
+        verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index 6737b1a..730275c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -16,11 +16,14 @@
 
 package com.android.server.wm;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
 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.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.mockito.Mockito.clearInvocations;
 
 import android.graphics.Rect;
@@ -91,6 +94,7 @@
         final Rect endBounds = new Rect(500, 500, 1000, 1000);
         mTaskFragment.setBounds(startBounds);
         doReturn(true).when(mTaskFragment).isVisible();
+        doReturn(true).when(mTaskFragment).isVisibleRequested();
 
         clearInvocations(mTransaction);
         mTaskFragment.setBounds(endBounds);
@@ -108,6 +112,25 @@
         verify(mTransaction).setWindowCrop(mLeash, 500, 500);
     }
 
+    @Test
+    public void testNotOkToAnimate_doNotStartChangeTransition() {
+        mockSurfaceFreezerSnapshot(mTaskFragment.mSurfaceFreezer);
+        final Rect startBounds = new Rect(0, 0, 1000, 1000);
+        final Rect endBounds = new Rect(500, 500, 1000, 1000);
+        mTaskFragment.setBounds(startBounds);
+        doReturn(true).when(mTaskFragment).isVisible();
+        doReturn(true).when(mTaskFragment).isVisibleRequested();
+
+        final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
+        displayPolicy.screenTurnedOff();
+
+        assertFalse(mTaskFragment.okToAnimate());
+
+        mTaskFragment.setBounds(endBounds);
+
+        verify(mTaskFragment, never()).initializeChangeTransition(any());
+    }
+
     /**
      * Tests that when a {@link TaskFragmentInfo} is generated from a {@link TaskFragment}, an
      * activity that has not yet been attached to a process because it is being initialized but
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
index c0ae8a5..3065e7d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestDisplayContent.java
@@ -168,6 +168,11 @@
                 doReturn(false).when(displayPolicy).hasStatusBar();
                 doReturn(false).when(newDisplay).supportsSystemDecorations();
             }
+            // Update the display policy to make the screen fully turned on so animation is allowed
+            displayPolicy.screenTurnedOn(null /* screenOnListener */);
+            displayPolicy.finishKeyguardDrawn();
+            displayPolicy.finishWindowsDrawn();
+            displayPolicy.finishScreenTurningOn();
             if (mStatusBarHeight > 0) {
                 doReturn(true).when(displayPolicy).hasStatusBar();
                 doAnswer(invocation -> {
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
index b6701dd..7dfb5ae 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java
@@ -69,10 +69,6 @@
     }
 
     @Override
-    public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) throws RemoteException {
-    }
-
-    @Override
     public void closeSystemDialogs(String reason) throws RemoteException {
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index f366f57..caaf4e4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -54,7 +54,6 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.WindowManager;
-import android.window.ITransitionPlayer;
 
 import androidx.test.filters.SmallTest;
 
@@ -313,11 +312,7 @@
         wallpaperWindow.setHasSurface(true);
 
         // Set-up mock shell transitions
-        final IBinder mockBinder = mock(IBinder.class);
-        final ITransitionPlayer mockPlayer = mock(ITransitionPlayer.class);
-        doReturn(mockBinder).when(mockPlayer).asBinder();
-        mWm.mAtmService.getTransitionController().registerTransitionPlayer(mockPlayer,
-                null /* appThread */);
+        registerTestTransitionPlayer();
 
         Transition transit =
                 mWm.mAtmService.getTransitionController().createTransition(TRANSIT_OPEN);
@@ -338,10 +333,21 @@
         assertFalse(token.isVisibleRequested());
         assertTrue(token.isVisible());
 
-        transit.onTransactionReady(transit.getSyncId(), mock(SurfaceControl.Transaction.class));
-        transit.finishTransition();
+        final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
+        token.finishSync(t, false /* cancel */);
+        transit.onTransactionReady(transit.getSyncId(), t);
+        dc.mTransitionController.finishTransition(transit);
         assertFalse(wallpaperWindow.isVisible());
         assertFalse(token.isVisible());
+
+        // Assume wallpaper was visible. When transaction is ready without wallpaper target,
+        // wallpaper should be requested to be invisible.
+        token.setVisibility(true);
+        transit = dc.mTransitionController.createTransition(TRANSIT_CLOSE);
+        dc.mTransitionController.collect(token);
+        transit.onTransactionReady(transit.getSyncId(), t);
+        assertFalse(token.isVisibleRequested());
+        assertTrue(token.isVisible());
     }
 
     private WindowState createWallpaperTargetWindow(DisplayContent dc) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContextListenerControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContextListenerControllerTests.java
index e5eba57..646647f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContextListenerControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContextListenerControllerTests.java
@@ -17,22 +17,35 @@
 package com.android.server.wm;
 
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.STATE_OFF;
+import static android.view.Display.STATE_ON;
 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
+import static android.window.WindowProvider.KEY_IS_WINDOW_PROVIDER_SERVICE;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 
 import android.app.IWindowToken;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.platform.test.annotations.Presubmit;
+import android.view.Display;
+import android.view.DisplayInfo;
 
 import androidx.test.filters.SmallTest;
 
@@ -55,12 +68,15 @@
     private static final int ANOTHER_UID = 1000;
 
     private final IBinder mClientToken = new Binder();
-    private WindowContainer mContainer;
+    private WindowContainer<?> mContainer;
 
     @Before
     public void setUp() {
         mController = new WindowContextListenerController();
         mContainer = createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDisplayContent);
+        // Make display on to verify configuration propagation.
+        mDefaultDisplay.getDisplayInfo().state = STATE_ON;
+        mDisplayContent.getDisplayInfo().state = STATE_ON;
     }
 
     @Test
@@ -76,7 +92,7 @@
 
         assertEquals(2, mController.mListeners.size());
 
-        final WindowContainer container = createTestWindowToken(TYPE_APPLICATION_OVERLAY,
+        final WindowContainer<?> container = createTestWindowToken(TYPE_APPLICATION_OVERLAY,
                 mDefaultDisplay);
         mController.registerWindowContainerListener(mClientToken, container, -1,
                 TYPE_APPLICATION_OVERLAY, null /* options */);
@@ -89,6 +105,7 @@
         assertEquals(container, listener.getWindowContainer());
     }
 
+    @UseTestDisplay
     @Test
     public void testRegisterWindowContextListenerClientConfigPropagation() {
         final TestWindowTokenClient clientToken = new TestWindowTokenClient();
@@ -107,7 +124,7 @@
         assertEquals(mDisplayContent.mDisplayId, clientToken.mDisplayId);
 
         // Update the WindowContainer.
-        final WindowContainer container = createTestWindowToken(TYPE_APPLICATION_OVERLAY,
+        final WindowContainer<?> container = createTestWindowToken(TYPE_APPLICATION_OVERLAY,
                 mDefaultDisplay);
         final Configuration config2 = container.getConfiguration();
         final Rect bounds2 = new Rect(0, 0, 20, 20);
@@ -174,7 +191,7 @@
                 .setDisplayContent(mDefaultDisplay)
                 .setFromClientToken(true)
                 .build();
-        final DisplayArea da = windowContextCreatedToken.getDisplayArea();
+        final DisplayArea<?> da = windowContextCreatedToken.getDisplayArea();
 
         mController.registerWindowContainerListener(mClientToken, windowContextCreatedToken,
                 TEST_UID, TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, null /* options */);
@@ -192,11 +209,12 @@
         // Let the Display to be created with the DualDisplay policy.
         final DisplayAreaPolicy.Provider policyProvider =
                 new DualDisplayAreaGroupPolicyTest.DualDisplayTestPolicyProvider();
-        Mockito.doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider();
+        doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider();
         // Create a DisplayContent with dual RootDisplayArea
         DualDisplayAreaGroupPolicyTest.DualDisplayContent dualDisplayContent =
                 new DualDisplayAreaGroupPolicyTest.DualDisplayContent
                  .Builder(mAtm, 1000, 1000).build();
+        dualDisplayContent.getDisplayInfo().state = STATE_ON;
         final DisplayArea.Tokens imeContainer = dualDisplayContent.getImeContainer();
         // Put the ImeContainer to the first sub-RootDisplayArea
         dualDisplayContent.mFirstRoot.placeImeContainer(imeContainer);
@@ -222,7 +240,62 @@
         assertThat(mController.getContainer(mClientToken)).isEqualTo(imeContainer);
     }
 
-    private class TestWindowTokenClient extends IWindowToken.Stub {
+    @Test
+    public void testConfigUpdateForSuspendedWindowContext() {
+        final TestWindowTokenClient mockToken = new TestWindowTokenClient();
+        spyOn(mockToken);
+
+        mContainer.getDisplayContent().getDisplayInfo().state = STATE_OFF;
+
+        final Configuration config1 = mContainer.getConfiguration();
+        final Rect bounds1 = new Rect(0, 0, 10, 10);
+        config1.windowConfiguration.setBounds(bounds1);
+        config1.densityDpi = 100;
+        mContainer.onRequestedOverrideConfigurationChanged(config1);
+
+        mController.registerWindowContainerListener(mockToken, mContainer, -1,
+                TYPE_APPLICATION_OVERLAY, null /* options */);
+
+        verify(mockToken, never()).onConfigurationChanged(any(), anyInt());
+
+        // Turn on the display and verify if the client receive the callback
+        Display display = mContainer.getDisplayContent().getDisplay();
+        spyOn(display);
+        Mockito.doAnswer(invocation -> {
+            final DisplayInfo info = mContainer.getDisplayContent().getDisplayInfo();
+            info.state = STATE_ON;
+            ((DisplayInfo) invocation.getArgument(0)).copyFrom(info);
+            return null;
+        }).when(display).getDisplayInfo(any(DisplayInfo.class));
+
+        mContainer.getDisplayContent().onDisplayChanged();
+
+        assertThat(mockToken.mConfiguration).isEqualTo(config1);
+        assertThat(mockToken.mDisplayId).isEqualTo(mContainer.getDisplayContent().getDisplayId());
+    }
+
+    @Test
+    public void testReportConfigUpdateForSuspendedWindowProviderService() {
+        final TestWindowTokenClient clientToken = new TestWindowTokenClient();
+        final Bundle options = new Bundle();
+        options.putBoolean(KEY_IS_WINDOW_PROVIDER_SERVICE, true);
+
+        mContainer.getDisplayContent().getDisplayInfo().state = STATE_OFF;
+
+        final Configuration config1 = mContainer.getConfiguration();
+        final Rect bounds1 = new Rect(0, 0, 10, 10);
+        config1.windowConfiguration.setBounds(bounds1);
+        config1.densityDpi = 100;
+        mContainer.onRequestedOverrideConfigurationChanged(config1);
+
+        mController.registerWindowContainerListener(clientToken, mContainer, -1,
+                TYPE_APPLICATION_OVERLAY, options);
+
+        assertThat(clientToken.mConfiguration).isEqualTo(config1);
+        assertThat(clientToken.mDisplayId).isEqualTo(mDisplayContent.mDisplayId);
+    }
+
+    private static class TestWindowTokenClient extends IWindowToken.Stub {
         private Configuration mConfiguration;
         private int mDisplayId;
         private boolean mRemoved;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 996b4b2..92fd682 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -198,6 +198,13 @@
         SystemServicesTestRule.checkHoldsLock(mWm.mGlobalLock);
 
         mDefaultDisplay = mWm.mRoot.getDefaultDisplay();
+        // Update the display policy to make the screen fully turned on so animation is allowed
+        final DisplayPolicy displayPolicy = mDefaultDisplay.getDisplayPolicy();
+        displayPolicy.screenTurnedOn(null /* screenOnListener */);
+        displayPolicy.finishKeyguardDrawn();
+        displayPolicy.finishWindowsDrawn();
+        displayPolicy.finishScreenTurningOn();
+
         mTransaction = mSystemServicesTestRule.mTransaction;
         mMockSession = mock(Session.class);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index 589f913..74cff10 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -94,6 +94,20 @@
     }
 
     @Test
+    public void testAddWindow_assignsLayers() {
+        final TestWindowToken token1 = createTestWindowToken(0, mDisplayContent);
+        final TestWindowToken token2 = createTestWindowToken(0, mDisplayContent);
+        final WindowState window1 = createWindow(null, TYPE_STATUS_BAR, token1, "window1");
+        final WindowState window2 = createWindow(null, TYPE_STATUS_BAR, token2, "window2");
+
+        token1.addWindow(window1);
+        token2.addWindow(window2);
+
+        assertEquals(token1.getLastLayer(), 0);
+        assertEquals(token2.getLastLayer(), 1);
+    }
+
+    @Test
     public void testChildRemoval() {
         final DisplayContent dc = mDisplayContent;
         final TestWindowToken token = createTestWindowToken(0, dc);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 722aee7..e5dc557 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -500,8 +500,6 @@
         mDisplayContent.assignChildLayers(mTransaction);
 
         assertWindowHigher(splitWindow1, belowTaskWindow);
-        assertWindowHigher(splitWindow1, belowTaskWindow);
-        assertWindowHigher(splitWindow2, belowTaskWindow);
         assertWindowHigher(splitWindow2, belowTaskWindow);
         assertWindowHigher(mDockedDividerWindow, splitWindow1);
         assertWindowHigher(mDockedDividerWindow, splitWindow2);
@@ -509,6 +507,39 @@
         assertWindowHigher(pinnedWindow, aboveTaskWindow);
     }
 
+
+    @Test
+    public void testDockedDividerPosition_noAboveTask() {
+        final Task pinnedTask =
+                createTask(mDisplayContent, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
+        final WindowState pinnedWindow =
+                createAppWindow(pinnedTask, ACTIVITY_TYPE_STANDARD, "pinnedWindow");
+
+        final Task belowTask =
+                createTask(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        final WindowState belowTaskWindow =
+                createAppWindow(belowTask, ACTIVITY_TYPE_STANDARD, "belowTaskWindow");
+
+        final Task splitScreenTask1 =
+                createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
+        final WindowState splitWindow1 =
+                createAppWindow(splitScreenTask1, ACTIVITY_TYPE_STANDARD, "splitWindow1");
+        final Task splitScreenTask2 =
+                createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
+        final WindowState splitWindow2 =
+                createAppWindow(splitScreenTask2, ACTIVITY_TYPE_STANDARD, "splitWindow2");
+        splitScreenTask1.setAdjacentTaskFragment(splitScreenTask2);
+        splitScreenTask2.setAdjacentTaskFragment(splitScreenTask1);
+
+        mDisplayContent.assignChildLayers(mTransaction);
+
+        assertWindowHigher(splitWindow1, belowTaskWindow);
+        assertWindowHigher(splitWindow2, belowTaskWindow);
+        assertWindowHigher(mDockedDividerWindow, splitWindow1);
+        assertWindowHigher(mDockedDividerWindow, splitWindow2);
+        assertWindowHigher(pinnedWindow, mDockedDividerWindow);
+    }
+
     @Test
     public void testAttachNavBarWhenEnteringRecents_expectNavBarHigherThanIme() {
         // create RecentsAnimationController
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index f05dd63..e19ea47 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -841,7 +841,7 @@
             try {
                 return mContext.bindIsolatedService(
                         mIntent,
-                        Context.BIND_AUTO_CREATE | mBindingFlags,
+                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE | mBindingFlags,
                         "hotword_detector_" + mInstanceNumber,
                         mExecutor,
                         serviceConnection);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index f4f06fd..96c78bc 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -191,7 +191,7 @@
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         mContext.registerReceiver(mBroadcastReceiver, filter, null, handler,
-                Context.RECEIVER_NOT_EXPORTED);
+                Context.RECEIVER_EXPORTED);
     }
 
     public boolean showSessionLocked(Bundle args, int flags,
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index abbce1c..98f619f 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1687,7 +1687,11 @@
      *
      * @param accountHandle The handle for the account retrieve a number for.
      * @return A string representation of the line 1 phone number.
+     * @deprecated use {@link SubscriptionManager#getPhoneNumber(int)} instead, which takes a
+     *             Telephony Subscription ID that can be retrieved with the {@code accountHandle}
+     *             from {@link TelephonyManager#getSubscriptionId(PhoneAccountHandle)}.
      */
+    @Deprecated
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges or default SMS app
     @RequiresPermission(anyOf = {
             android.Manifest.permission.READ_PHONE_STATE,
diff --git a/telephony/common/Android.bp b/telephony/common/Android.bp
index 1cacc03..b0a812b 100644
--- a/telephony/common/Android.bp
+++ b/telephony/common/Android.bp
@@ -21,7 +21,10 @@
 
 filegroup {
     name: "framework-mms-shared-srcs",
-    visibility: ["//packages/apps/Bluetooth"],
+    visibility: [
+        "//packages/apps/Bluetooth",
+	"//packages/modules/Bluetooth/android/app",
+    ],
     srcs: [
         "com/google/android/mms/**/*.java",
     ],
diff --git a/telephony/java/android/service/euicc/EuiccService.java b/telephony/java/android/service/euicc/EuiccService.java
index fcbb008..fabe612 100644
--- a/telephony/java/android/service/euicc/EuiccService.java
+++ b/telephony/java/android/service/euicc/EuiccService.java
@@ -255,6 +255,12 @@
     public static final String EXTRA_RESOLUTION_CARD_ID =
             "android.service.euicc.extra.RESOLUTION_CARD_ID";
 
+    /**
+     * Intent extra set for resolution requests containing an int indicating the current port index.
+     */
+    public static final String EXTRA_RESOLUTION_PORT_INDEX =
+            "android.service.euicc.extra.RESOLUTION_PORT_INDEX";
+
     /** @hide */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(prefix = { "RESULT_" }, value = {
@@ -579,9 +585,32 @@
      * @return the result of the switch operation. May be one of the predefined {@code RESULT_}
      *     constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
      * @see android.telephony.euicc.EuiccManager#switchToSubscription
+     *
+     * @deprecated prefer {@link #onSwitchToSubscriptionWithPort(int, int, String, boolean)}
      */
-    public abstract @Result int onSwitchToSubscription(int slotId, @Nullable String iccid,
-            boolean forceDeactivateSim);
+    @Deprecated public abstract @Result int onSwitchToSubscription(int slotId,
+            @Nullable String iccid, boolean forceDeactivateSim);
+
+    /**
+     * Switch to the given subscription.
+     *
+     * @param slotId ID of the SIM slot to use for the operation.
+     * @param portIndex which port on the eUICC to use
+     * @param iccid the ICCID of the subscription to enable. May be null, in which case the current
+     *     profile should be deactivated and no profile should be activated to replace it - this is
+     *     equivalent to a physical SIM being ejected.
+     * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
+     *     eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM}
+     *     should be returned to allow the user to consent to this operation first.
+     * @return the result of the switch operation. May be one of the predefined {@code RESULT_}
+     *     constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
+     * @see android.telephony.euicc.EuiccManager#switchToSubscription
+     */
+    public @Result int onSwitchToSubscriptionWithPort(int slotId, int portIndex,
+            @Nullable String iccid, boolean forceDeactivateSim) {
+        // stub implementation, LPA needs to implement this
+        throw new UnsupportedOperationException("LPA must override onSwitchToSubscriptionWithPort");
+    }
 
     /**
      * Update the nickname of the given subscription.
@@ -821,13 +850,13 @@
                 }
             });
         }
-
         @Override
-        public void switchToSubscription(int slotId, String iccid, boolean forceDeactivateSim,
-                ISwitchToSubscriptionCallback callback) {
+        public void switchToSubscription(int slotId, int portIndex, String iccid,
+                boolean forceDeactivateSim, ISwitchToSubscriptionCallback callback) {
             mExecutor.execute(new Runnable() {
                 @Override
                 public void run() {
+                    // TODO(b/207392528: use portIndex API once implemented)
                     int result =
                             EuiccService.this.onSwitchToSubscription(
                                     slotId, iccid, forceDeactivateSim);
diff --git a/telephony/java/android/service/euicc/IEuiccService.aidl b/telephony/java/android/service/euicc/IEuiccService.aidl
index bb7b569..aa30c9e 100644
--- a/telephony/java/android/service/euicc/IEuiccService.aidl
+++ b/telephony/java/android/service/euicc/IEuiccService.aidl
@@ -48,7 +48,7 @@
             in IGetDefaultDownloadableSubscriptionListCallback callback);
     void getEuiccInfo(int slotId, in IGetEuiccInfoCallback callback);
     void deleteSubscription(int slotId, String iccid, in IDeleteSubscriptionCallback callback);
-    void switchToSubscription(int slotId, String iccid, boolean forceDeactivateSim,
+    void switchToSubscription(int slotId, int portIndex, String iccid, boolean forceDeactivateSim,
             in ISwitchToSubscriptionCallback callback);
     void updateSubscriptionNickname(int slotId, String iccid, String nickname,
             in IUpdateSubscriptionNicknameCallback callback);
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 23cf511..e88106c 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -1,6 +1,8 @@
 package android.telephony;
 
 import android.annotation.IntDef;
+import android.net.NetworkAgent;
+import android.net.NetworkCapabilities;
 import android.telecom.Connection;
 import android.telephony.data.ApnSetting;
 
@@ -664,4 +666,59 @@
         TelephonyManager.THERMAL_MITIGATION_RESULT_INVALID_STATE,
         TelephonyManager.THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR})
     public @interface ThermalMitigationResult {}
+
+    /**
+     * Per Android API guideline 8.15, annotation can't be public APIs. So duplicate
+     * android.net.NetworkCapabilities.NetCapability here. Must update here when new capabilities
+     * are added in {@link NetworkCapabilities}.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "NET_CAPABILITY_" }, value = {
+            NetworkCapabilities.NET_CAPABILITY_MMS,
+            NetworkCapabilities.NET_CAPABILITY_SUPL,
+            NetworkCapabilities.NET_CAPABILITY_DUN,
+            NetworkCapabilities.NET_CAPABILITY_FOTA,
+            NetworkCapabilities.NET_CAPABILITY_IMS,
+            NetworkCapabilities.NET_CAPABILITY_CBS,
+            NetworkCapabilities.NET_CAPABILITY_WIFI_P2P,
+            NetworkCapabilities.NET_CAPABILITY_IA,
+            NetworkCapabilities.NET_CAPABILITY_RCS,
+            NetworkCapabilities.NET_CAPABILITY_XCAP,
+            NetworkCapabilities.NET_CAPABILITY_EIMS,
+            NetworkCapabilities.NET_CAPABILITY_NOT_METERED,
+            NetworkCapabilities.NET_CAPABILITY_INTERNET,
+            NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED,
+            NetworkCapabilities.NET_CAPABILITY_TRUSTED,
+            NetworkCapabilities.NET_CAPABILITY_NOT_VPN,
+            NetworkCapabilities.NET_CAPABILITY_VALIDATED,
+            NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL,
+            NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING,
+            NetworkCapabilities.NET_CAPABILITY_FOREGROUND,
+            NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED,
+            NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED,
+            NetworkCapabilities.NET_CAPABILITY_OEM_PAID,
+            NetworkCapabilities.NET_CAPABILITY_MCX,
+            NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY,
+            NetworkCapabilities.NET_CAPABILITY_TEMPORARILY_NOT_METERED,
+            NetworkCapabilities.NET_CAPABILITY_OEM_PRIVATE,
+            NetworkCapabilities.NET_CAPABILITY_VEHICLE_INTERNAL,
+            NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED,
+            NetworkCapabilities.NET_CAPABILITY_ENTERPRISE,
+            NetworkCapabilities.NET_CAPABILITY_VSIM,
+            NetworkCapabilities.NET_CAPABILITY_BIP,
+            NetworkCapabilities.NET_CAPABILITY_HEAD_UNIT,
+    })
+    public @interface NetCapability { }
+
+    /**
+     * Per Android API guideline 8.15, annotation can't be public APIs. So duplicate
+     * android.net.NetworkAgent.ValidationStatus here. Must update here when new validation status
+     * are added in {@link NetworkAgent}.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "VALIDATION_STATUS_" }, value = {
+            NetworkAgent.VALIDATION_STATUS_VALID,
+            NetworkAgent.VALIDATION_STATUS_NOT_VALID
+    })
+    public @interface ValidationStatus {}
 }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 2dfa9a45..6f92c31 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -5116,13 +5116,11 @@
     public static final String KEY_APN_PRIORITY_STRING_ARRAY = "apn_priority_string_array";
 
     /**
-     * Network capability priority for determine the satisfy order in telephony. This is used when
-     * the network only allows single PDN. The priority is from the lowest 0 to the highest 100.
-     * The long-lived network request usually has the lowest priority. This allows other short-lived
-     * requests like MMS requests to be established. Emergency request always has the highest
-     * priority.
+     * Network capability priority for determine the satisfy order in telephony. The priority is
+     * from the lowest 0 to the highest 100. The long-lived network shall have the lowest priority.
+     * This allows other short-lived requests like MMS requests to be established. Emergency request
+     * always has the highest priority.
      *
-     * // TODO: Remove KEY_APN_PRIORITY_STRING_ARRAY
      * @hide
      */
     public static final String KEY_TELEPHONY_NETWORK_CAPABILITY_PRIORITIES_STRING_ARRAY =
@@ -5132,17 +5130,17 @@
      * Defines the rules for data retry.
      *
      * The syntax of the retry rule:
-     * 1. Retry based on {@link NetworkCapabilities}
-     * "capabilities=[netCaps1|netCaps2|...], [retry_interval=x], [backoff=[true|false]],
-     *     [maximum_retries=y]"
+     * 1. Retry based on {@link NetworkCapabilities}. Note that only APN-type network capabilities
+     *    are supported.
+     * "capabilities=[netCaps1|netCaps2|...], [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
      *
      * 2. Retry based on {@link DataFailCause}
-     * "fail_causes=[cause1|cause2|cause3|...], [retry_interval=x], [backoff=[true|false]],
-     *     [maximum_retries=y]"
+     * "fail_causes=[cause1|cause2|cause3|..], [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
      *
-     * 3. Retry based on {@link NetworkCapabilities} and {@link DataFailCause}
+     * 3. Retry based on {@link NetworkCapabilities} and {@link DataFailCause}. Note that only
+     *    APN-type network capabilities are supported.
      * "capabilities=[netCaps1|netCaps2|...], fail_causes=[cause1|cause2|cause3|...],
-     *     [retry_interval=x], [backoff=[true|false]], [maximum_retries=y]"
+     *     [retry_interval=n1|n2|n3|n4...], [maximum_retries=n]"
      *
      * For example,
      * "capabilities=eims, retry_interval=1000, maximum_retries=20" means if the attached
@@ -5151,7 +5149,12 @@
      *
      * "fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|2253|2254
      * , maximum_retries=0" means for those fail causes, never retry with timers. Note that
-     * when environment changes, retry can still happens.
+     * when environment changes, retry can still happen.
+     *
+     * "capabilities=internet|enterprise|dun|ims|fota, retry_interval=2500|3000|"
+     * "5000|10000|15000|20000|40000|60000|120000|240000|600000|1200000|1800000"
+     * "1800000, maximum_retries=20" means for those capabilities, retry happens in 2.5s, 3s, 5s,
+     * 10s, 15s, 20s, 40s, 1m, 2m, 4m, 10m, 20m, 30m, 30m, 30m, until reaching 20 retries.
      *
      * // TODO: remove KEY_CARRIER_DATA_CALL_RETRY_CONFIG_STRINGS
      * @hide
@@ -5207,16 +5210,6 @@
             "call_composer_picture_server_url_string";
 
     /**
-     * For Android 11, provide a temporary solution for OEMs to use the lower of the two MTU values
-     * for IPv4 and IPv6 if both are sent.
-     * TODO: remove in later release
-     *
-     * @hide
-     */
-    public static final String KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED =
-            "use_lower_mtu_value_if_both_received";
-
-    /**
      * Determines the default RTT mode.
      *
      * Upon first boot, when the user has not yet set a value for their preferred RTT mode,
@@ -5951,6 +5944,9 @@
                 "enterprise:0", "default:1", "mms:2", "supl:2", "dun:2", "hipri:3", "fota:2",
                 "ims:2", "cbs:2", "ia:2", "emergency:2", "mcx:3", "xcap:3"
         });
+
+        // Do not modify the priority unless you know what you are doing. This will have significant
+        // impacts on the order of data network setup.
         sDefaults.putStringArray(
                 KEY_TELEPHONY_NETWORK_CAPABILITY_PRIORITIES_STRING_ARRAY, new String[] {
                         "eims:90", "supl:80", "mms:70", "xcap:70", "cbs:50", "mcx:50", "fota:50",
@@ -5961,16 +5957,16 @@
                         "capabilities=eims, retry_interval=1000, maximum_retries=20",
                         "fail_causes=8|27|28|29|30|32|33|35|50|51|111|-5|-6|65537|65538|-3|2253|"
                                 + "2254, maximum_retries=0", // No retry for those causes
-                        "capabilities=internet|enterprise|dun|ims|fota, retry_interval=2000, "
-                                + "backoff=true, maximum_retries=13",
-                        "capabilities=mms|supl|cbs, retry_interval=2000"
+                        "capabilities=mms|supl|cbs, retry_interval=2000",
+                        "capabilities=internet|enterprise|dun|ims|fota, retry_interval=2500|3000|"
+                                + "5000|10000|15000|20000|40000|60000|120000|240000|"
+                                + "600000|1200000|1800000, maximum_retries=20"
                 });
         sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]);
         sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
         sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
         sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
         sDefaults.putString(KEY_CALL_COMPOSER_PICTURE_SERVER_URL_STRING, "");
-        sDefaults.putBoolean(KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED, false);
         sDefaults.putBoolean(KEY_USE_ACS_FOR_RCS_BOOL, false);
         sDefaults.putBoolean(KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL, true);
         sDefaults.putInt(KEY_DEFAULT_RTT_MODE_INT, 0);
@@ -5984,7 +5980,7 @@
         sDefaults.putString(KEY_CARRIER_PROVISIONING_APP_STRING, "");
         sDefaults.putBoolean(KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL, false);
         sDefaults.putBoolean(KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false);
-        sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, false);
+        sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, true);
         sDefaults.putBoolean(KEY_VONR_ENABLED_BOOL, false);
     }
 
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index 88efe1f..56bf303 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -1076,6 +1076,13 @@
      */
     public static final int SERVICE_TEMPORARILY_UNAVAILABLE = 0x10009;
 
+    /**
+     * The request is not supported by the vendor.
+     *
+     * @hide
+     */
+    public static final int REQUEST_NOT_SUPPORTED = 0x1000A;
+
     private static final Map<Integer, String> sFailCauseMap;
     static {
         sFailCauseMap = new HashMap<>();
diff --git a/telephony/java/android/telephony/ImsManager.java b/telephony/java/android/telephony/ImsManager.java
index a25abc9..fc76f99 100644
--- a/telephony/java/android/telephony/ImsManager.java
+++ b/telephony/java/android/telephony/ImsManager.java
@@ -135,7 +135,7 @@
             throw new IllegalArgumentException("Invalid subscription ID: " + subscriptionId);
         }
 
-        return new ImsMmTelManager(subscriptionId, sTelephonyCache);
+        return new ImsMmTelManager(mContext, subscriptionId, sTelephonyCache);
     }
 
     /**
diff --git a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
index 2ff4ac5..9cb80f1 100644
--- a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
+++ b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java
@@ -71,12 +71,7 @@
             @Nullable List<SignalThresholdInfo> signalThresholdInfos,
             boolean isReportingRequestedWhileIdle,
             boolean isSystemThresholdReportingRequestedWhileIdle) {
-        // System app (like Bluetooth) can specify the request to report system thresholds while
-        // device is idle (with permission protection). In this case, the request doesn't need to
-        // provide a non-empty list of SignalThresholdInfo which is only asked for public apps.
-        if (!isSystemThresholdReportingRequestedWhileIdle) {
-            validate(signalThresholdInfos);
-        }
+        validate(signalThresholdInfos, isSystemThresholdReportingRequestedWhileIdle);
 
         mSignalThresholdInfos = signalThresholdInfos;
         mIsReportingRequestedWhileIdle = isReportingRequestedWhileIdle;
@@ -274,8 +269,12 @@
      * Throw IAE if SignalThresholdInfo collection is null or empty,
      * or the SignalMeasurementType for the same RAN in the collection is not unique.
      */
-    private static void validate(Collection<SignalThresholdInfo> infos) {
-        if (infos == null || infos.isEmpty()) {
+    private static void validate(Collection<SignalThresholdInfo> infos,
+            boolean isSystemThresholdReportingRequestedWhileIdle) {
+        // System app (like Bluetooth) can specify the request to report system thresholds while
+        // device is idle (with permission protection). In this case, the request doesn't need to
+        // provide a non-empty list of SignalThresholdInfo which is only asked for public apps.
+        if (infos == null || (infos.isEmpty() && !isSystemThresholdReportingRequestedWhileIdle)) {
             throw new IllegalArgumentException("SignalThresholdInfo collection is null or empty");
         }
 
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 63a7acf..d11ad91 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -222,6 +222,11 @@
     private boolean mAreUiccApplicationsEnabled = true;
 
     /**
+     * The port index of the Uicc card.
+     */
+    private final int mPortIndex;
+
+    /**
      * Public copy constructor.
      * @hide
      */
@@ -274,6 +279,22 @@
             int carrierId, int profileClass, int subType, @Nullable String groupOwner,
             @Nullable UiccAccessRule[] carrierConfigAccessRules,
             boolean areUiccApplicationsEnabled) {
+        this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
+                roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString,
+                cardId, isOpportunistic, groupUUID, isGroupDisabled, carrierId, profileClass,
+                subType, groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, 0);
+    }
+    /**
+     * @hide
+     */
+    public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
+            CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
+            Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded,
+            @Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId,
+            boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled,
+            int carrierId, int profileClass, int subType, @Nullable String groupOwner,
+            @Nullable UiccAccessRule[] carrierConfigAccessRules,
+            boolean areUiccApplicationsEnabled, int portIndex) {
         this.mId = id;
         this.mIccId = iccId;
         this.mSimSlotIndex = simSlotIndex;
@@ -300,8 +321,8 @@
         this.mGroupOwner = groupOwner;
         this.mCarrierConfigAccessRules = carrierConfigAccessRules;
         this.mAreUiccApplicationsEnabled = areUiccApplicationsEnabled;
+        this.mPortIndex = portIndex;
     }
-
     /**
      * @return the subscription ID.
      */
@@ -477,7 +498,10 @@
      *
      * @return the number of this subscription, or an empty string if one of these requirements is
      * not met
+     * @deprecated use {@link SubscriptionManager#getPhoneNumber(int)} instead, which takes a
+     *             {@link #getSubscriptionId() subscription ID}.
      */
+    @Deprecated
     public String getNumber() {
         return mNumber;
     }
@@ -737,6 +761,14 @@
     public int getCardId() {
         return this.mCardId;
     }
+    /**
+     * Returns the port index of the SIM card which contains the subscription.
+     *
+     * @return the portIndex
+     */
+    public int getPortIndex() {
+        return this.mPortIndex;
+    }
 
     /**
      * Set whether the subscription's group is disabled.
@@ -783,6 +815,7 @@
             UiccAccessRule[] nativeAccessRules = source.createTypedArray(UiccAccessRule.CREATOR);
             String cardString = source.readString();
             int cardId = source.readInt();
+            int portId = source.readInt();
             boolean isOpportunistic = source.readBoolean();
             String groupUUID = source.readString();
             boolean isGroupDisabled = source.readBoolean();
@@ -800,7 +833,7 @@
                     carrierName, nameSource, iconTint, number, dataRoaming, /* icon= */ null,
                     mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, cardId,
                     isOpportunistic, groupUUID, isGroupDisabled, carrierid, profileClass, subType,
-                    groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled);
+                    groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, portId);
             info.setAssociatedPlmns(ehplmns, hplmns);
             return info;
         }
@@ -830,6 +863,7 @@
         dest.writeTypedArray(mNativeAccessRules, flags);
         dest.writeString(mCardString);
         dest.writeInt(mCardId);
+        dest.writeInt(mPortIndex);
         dest.writeBoolean(mIsOpportunistic);
         dest.writeString(mGroupUUID == null ? null : mGroupUUID.toString());
         dest.writeBoolean(mIsGroupDisabled);
@@ -876,6 +910,7 @@
                 + " mnc=" + mMnc + " countryIso=" + mCountryIso + " isEmbedded=" + mIsEmbedded
                 + " nativeAccessRules=" + Arrays.toString(mNativeAccessRules)
                 + " cardString=" + cardStringToPrint + " cardId=" + mCardId
+                + " portIndex=" + mPortIndex
                 + " isOpportunistic=" + mIsOpportunistic + " groupUUID=" + mGroupUUID
                 + " isGroupDisabled=" + mIsGroupDisabled
                 + " profileClass=" + mProfileClass
@@ -892,7 +927,7 @@
         return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded,
                 mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc, mCountryIso, mCardString,
                 mCardId, mDisplayName, mCarrierName, mNativeAccessRules, mIsGroupDisabled,
-                mCarrierId, mProfileClass, mGroupOwner, mAreUiccApplicationsEnabled);
+                mCarrierId, mProfileClass, mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex);
     }
 
     @Override
@@ -925,6 +960,7 @@
                 && Objects.equals(mCountryIso, toCompare.mCountryIso)
                 && Objects.equals(mCardString, toCompare.mCardString)
                 && Objects.equals(mCardId, toCompare.mCardId)
+                && mPortIndex == toCompare.mPortIndex
                 && Objects.equals(mGroupOwner, toCompare.mGroupOwner)
                 && TextUtils.equals(mDisplayName, toCompare.mDisplayName)
                 && TextUtils.equals(mCarrierName, toCompare.mCarrierName)
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d5315ac..1fab89e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1128,6 +1128,52 @@
      */
     public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX";
 
+    /**
+     * A source of phone number: the EF-MSISDN (see 3GPP TS 31.102),
+     * or EF-MDN for CDMA (see 3GPP2 C.P0065-B), from UICC application.
+     *
+     * <p>The availability and a of the number depends on the carrier.
+     * The number may be updated by over-the-air update to UICC applications
+     * from the carrier, or by other means with physical access to the SIM.
+     */
+    public static final int PHONE_NUMBER_SOURCE_UICC = 1;
+
+    /**
+     * A source of phone number: provided by an app that has carrier privilege.
+     *
+     * <p>The number is intended to be set by a carrier app knowing the correct number
+     * which is, for example, different from the number in {@link #PHONE_NUMBER_SOURCE_UICC UICC}
+     * for some reason.
+     * The number is not available until a carrier app sets one via
+     * {@link #setCarrierPhoneNumber(int, String)}.
+     * The app can update the number with the same API should the number change.
+     */
+    public static final int PHONE_NUMBER_SOURCE_CARRIER = 2;
+
+    /**
+     * A source of phone number: provided by IMS (IP Multimedia Subsystem) implementation.
+     * When IMS service is registered (as indicated by
+     * {@link android.telephony.ims.RegistrationManager.RegistrationCallback#onRegistered(int)})
+     * the IMS implementation may return P-Associated-Uri SIP headers (RFC 3455). The URIs
+     * are the user’s public user identities known to the network (see 3GPP TS 24.229 5.4.1.2),
+     * and the phone number is typically one of them (see “global number” in 3GPP TS 23.003 13.4).
+     *
+     * <p>This source provides the phone number from the last IMS registration.
+     * IMS registration may happen on every device reboot or other network condition changes.
+     * The number will be updated should the associated URI change after an IMS registration.
+     */
+    public static final int PHONE_NUMBER_SOURCE_IMS = 3;
+
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"PHONE_NUMBER_SOURCE"},
+            value = {
+                    PHONE_NUMBER_SOURCE_UICC,
+                    PHONE_NUMBER_SOURCE_CARRIER,
+                    PHONE_NUMBER_SOURCE_IMS,
+            })
+    public @interface PhoneNumberSource {}
+
     private final Context mContext;
 
     // Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing
@@ -3763,4 +3809,132 @@
                 RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME,
                 null, bundle);
     }
+
+    /**
+     * Returns the phone number for the given {@code subId} and {@code source},
+     * or an empty string if not available.
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS}, or
+     * READ_PRIVILEGED_PHONE_STATE permission (can only be granted to apps preloaded on device),
+     * or that the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID}
+     *                       for the default one.
+     * @param source the source of the phone number, one of the PHONE_NUMBER_SOURCE_* constants.
+     * @return the phone number, or an empty string if not available.
+     * @throws IllegalArgumentException if {@code source} is invalid.
+     * @throws IllegalStateException if the telephony process is not currently available.
+     * @throws SecurityException if the caller doesn't have permissions required.
+     * @see #PHONE_NUMBER_SOURCE_UICC
+     * @see #PHONE_NUMBER_SOURCE_CARRIER
+     * @see #PHONE_NUMBER_SOURCE_IMS
+     */
+    @SuppressAutoDoc // No support for carrier privileges (b/72967236)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PHONE_NUMBERS,
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+    })
+    @NonNull
+    public String getPhoneNumber(int subscriptionId, @PhoneNumberSource int source) {
+        if (subscriptionId == DEFAULT_SUBSCRIPTION_ID) {
+            subscriptionId = getDefaultSubscriptionId();
+        }
+        if (source != PHONE_NUMBER_SOURCE_UICC
+                && source != PHONE_NUMBER_SOURCE_CARRIER
+                && source != PHONE_NUMBER_SOURCE_IMS) {
+            throw new IllegalArgumentException("invalid source " + source);
+        }
+        try {
+            ISub iSub = TelephonyManager.getSubscriptionService();
+            if (iSub != null) {
+                return iSub.getPhoneNumber(subscriptionId, source,
+                        mContext.getOpPackageName(), mContext.getAttributionTag());
+            } else {
+                throw new IllegalStateException("subscription service unavailable.");
+            }
+        } catch (RemoteException ex) {
+            throw ex.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Returns the phone number for the given {@code subId}, or an empty string if
+     * not available.
+     *
+     * <p>This API is built up on {@link #getPhoneNumber(int, int)}, but picks
+     * from available sources in the following order: {@link #PHONE_NUMBER_SOURCE_CARRIER}
+     * > {@link #PHONE_NUMBER_SOURCE_UICC} > {@link #PHONE_NUMBER_SOURCE_IMS}.
+     *
+     * <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_NUMBERS READ_PHONE_NUMBERS}, or
+     * READ_PRIVILEGED_PHONE_STATE permission (can only be granted to apps preloaded on device),
+     * or that the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID}
+     *                       for the default one.
+     * @return the phone number, or an empty string if not available.
+     * @throws IllegalStateException if the telephony process is not currently available.
+     * @throws SecurityException if the caller doesn't have permissions required.
+     * @see #getPhoneNumber(int, int)
+     */
+    @SuppressAutoDoc // No support for carrier privileges (b/72967236)
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PHONE_NUMBERS,
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+    })
+    @NonNull
+    public String getPhoneNumber(int subscriptionId) {
+        if (subscriptionId == DEFAULT_SUBSCRIPTION_ID) {
+            subscriptionId = getDefaultSubscriptionId();
+        }
+        try {
+            ISub iSub = TelephonyManager.getSubscriptionService();
+            if (iSub != null) {
+                return iSub.getPhoneNumberFromFirstAvailableSource(subscriptionId,
+                        mContext.getOpPackageName(), mContext.getAttributionTag());
+            } else {
+                throw new IllegalStateException("subscription service unavailable.");
+            }
+        } catch (RemoteException ex) {
+            throw ex.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
+     * Sets the phone number for the given {@code subId} for source
+     * {@link #PHONE_NUMBER_SOURCE_CARRIER carrier}.
+     * Sets an empty string to remove the previously set phone number.
+     *
+     * <p>Requires Permission: the calling app has carrier privileges
+     * (see {@link TelephonyManager#hasCarrierPrivileges}).
+     *
+     * @param subscriptionId the subscription ID, or {@link #DEFAULT_SUBSCRIPTION_ID}
+     *                       for the default one.
+     * @param number the phone number, or an empty string to remove the previously set number.
+     * @throws IllegalStateException if the telephony process is not currently available.
+     * @throws NullPointerException if {@code number} is {@code null}.
+     * @throws SecurityException if the caller doesn't have permissions required.
+     */
+    public void setCarrierPhoneNumber(int subscriptionId, @NonNull String number) {
+        if (subscriptionId == DEFAULT_SUBSCRIPTION_ID) {
+            subscriptionId = getDefaultSubscriptionId();
+        }
+        if (number == null) {
+            throw new NullPointerException("invalid number null");
+        }
+        try {
+            ISub iSub = TelephonyManager.getSubscriptionService();
+            if (iSub != null) {
+                iSub.setPhoneNumber(subscriptionId, PHONE_NUMBER_SOURCE_CARRIER, number,
+                        mContext.getOpPackageName(), mContext.getAttributionTag());
+            } else {
+                throw new IllegalStateException("subscription service unavailable.");
+            }
+        } catch (RemoteException ex) {
+            throw ex.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 50f2abd..ae2facd 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -131,6 +131,8 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -144,6 +146,7 @@
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
 
+
 /**
  * Provides access to information about the telephony services on
  * the device. Applications can use the methods in this class to
@@ -3462,15 +3465,39 @@
      * @see #SIM_STATE_PRESENT
      *
      * @hide
+     * @deprecated instead use {@link #getSimCardState(int, int)}
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @Deprecated
     public @SimState int getSimCardState(int physicalSlotIndex) {
-        int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex));
+        int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex, DEFAULT_PORT_INDEX));
         return getSimCardStateFromSimState(simState);
     }
 
     /**
+     * Returns a constant indicating the state of the device SIM card in a physical slot and
+     * port index.
+     *
+     * @param physicalSlotIndex physical slot index
+     * @param portIndex The port index is an enumeration of the ports available on the UICC.
+     *                  Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+     *
+     * @see #SIM_STATE_UNKNOWN
+     * @see #SIM_STATE_ABSENT
+     * @see #SIM_STATE_CARD_IO_ERROR
+     * @see #SIM_STATE_CARD_RESTRICTED
+     * @see #SIM_STATE_PRESENT
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @SimState int getSimCardState(int physicalSlotIndex, int portIndex) {
+        int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex, portIndex));
+        return getSimCardStateFromSimState(simState);
+    }
+    /**
      * Converts SIM state to SIM card state.
      * @param simState
      * @return SIM card state
@@ -3490,13 +3517,19 @@
     /**
      * Converts a physical slot index to logical slot index.
      * @param physicalSlotIndex physical slot index
+     * @param portIndex The port index is an enumeration of the ports available on the UICC.
+     *                  Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
      * @return logical slot index
      */
-    private int getLogicalSlotIndex(int physicalSlotIndex) {
+    private int getLogicalSlotIndex(int physicalSlotIndex, int portIndex) {
         UiccSlotInfo[] slotInfos = getUiccSlotsInfo();
         if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.length
                 && slotInfos[physicalSlotIndex] != null) {
-            return slotInfos[physicalSlotIndex].getLogicalSlotIdx();
+            for (UiccPortInfo portInfo : slotInfos[physicalSlotIndex].getPorts()) {
+                if (portInfo.getPortIndex() == portIndex) {
+                    return portInfo.getLogicalSlotIndex();
+                }
+            }
         }
 
         return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
@@ -3536,12 +3569,42 @@
      * @see #SIM_STATE_LOADED
      *
      * @hide
+     * @deprecated instead use {@link #getSimApplicationState(int, int)}
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @Deprecated
     public @SimState int getSimApplicationState(int physicalSlotIndex) {
         int simState =
-                SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex));
+                SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex,
+                        DEFAULT_PORT_INDEX));
+        return getSimApplicationStateFromSimState(simState);
+    }
+
+    /**
+     * Returns a constant indicating the state of the card applications on the device SIM card in
+     * a physical slot.
+     *
+     * @param physicalSlotIndex physical slot index
+     * @param portIndex The port index is an enumeration of the ports available on the UICC.
+     *                  Use {@link UiccPortInfo#getPortIndex()} to get portIndex.
+     *
+     * @see #SIM_STATE_UNKNOWN
+     * @see #SIM_STATE_PIN_REQUIRED
+     * @see #SIM_STATE_PUK_REQUIRED
+     * @see #SIM_STATE_NETWORK_LOCKED
+     * @see #SIM_STATE_NOT_READY
+     * @see #SIM_STATE_PERM_DISABLED
+     * @see #SIM_STATE_LOADED
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public @SimState int getSimApplicationState(int physicalSlotIndex, int portIndex) {
+        int simState =
+                SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex,
+                        portIndex));
         return getSimApplicationStateFromSimState(simState);
     }
 
@@ -3931,8 +3994,8 @@
      * <p>
      * If the caller has carrier priviliges on any active subscription, then they have permission to
      * get simple information like the card ID ({@link UiccCardInfo#getCardId()}), whether the card
-     * is an eUICC ({@link UiccCardInfo#isEuicc()}), and the slot index where the card is inserted
-     * ({@link UiccCardInfo#getSlotIndex()}).
+     * is an eUICC ({@link UiccCardInfo#isEuicc()}), and the physical slot index where the card is
+     * inserted ({@link UiccCardInfo#getPhysicalSlotIndex()}.
      * <p>
      * To get private information such as the EID ({@link UiccCardInfo#getEid()}) or ICCID
      * ({@link UiccCardInfo#getIccId()}), the caller must have carrier priviliges on that specific
@@ -3976,7 +4039,7 @@
             if (telephony == null) {
                 return null;
             }
-            return telephony.getUiccSlotsInfo();
+            return telephony.getUiccSlotsInfo(mContext.getOpPackageName());
         } catch (RemoteException e) {
             return null;
         }
@@ -4009,8 +4072,13 @@
      *        size should be same as {@link #getUiccSlotsInfo()}.
      * @return boolean Return true if the switch succeeds, false if the switch fails.
      * @hide
+     * @deprecated {@link #setSimSlotMapping(Collection, Executor, Consumer)}
      */
+     // TODO: once integrating the HAL changes we can  convert int[] to List<UiccSlotMapping> and
+     // converge API's in ITelephony.aidl and PhoneInterfaceManager
+
     @SystemApi
+    @Deprecated
     @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean switchSlots(int[] physicalSlots) {
         try {
@@ -4025,6 +4093,109 @@
     }
 
     /**
+     * @param slotMapping Logical to physical slot and port mapping.
+     * @return {@code true} if slotMapping is valid.
+     * @return {@code false} if slotMapping is invalid.
+     *
+     * slotMapping is invalid if there are different entries (physical slot + port) mapping to the
+     * same logical slot or if there are same {physical slot + port} mapping to the different
+     * logical slot
+     * @hide
+     */
+    private static boolean isSlotMappingValid(@NonNull Collection<UiccSlotMapping> slotMapping) {
+        // Grouping the collection by logicalSlotIndex, finding different entries mapping to the
+        // same logical slot
+        Map<Integer, List<UiccSlotMapping>> slotMappingInfo = slotMapping.stream().collect(
+                Collectors.groupingBy(UiccSlotMapping::getLogicalSlotIndex));
+        for (Map.Entry<Integer, List<UiccSlotMapping>> entry : slotMappingInfo.entrySet()) {
+            List<UiccSlotMapping> logicalSlotMap = entry.getValue();
+            if (logicalSlotMap.size() > 1) {
+                // duplicate logicalSlotIndex found
+                return false;
+            }
+        }
+
+        // Grouping the collection by physical slot and port, finding same entries mapping to the
+        // different logical slot
+        Map<List<Integer>, List<UiccSlotMapping>> slotMapInfos = slotMapping.stream().collect(
+                Collectors.groupingBy(
+                        slot -> Arrays.asList(slot.getPhysicalSlotIndex(), slot.getPortIndex())));
+        for (Map.Entry<List<Integer>, List<UiccSlotMapping>> entry : slotMapInfos.entrySet()) {
+            List<UiccSlotMapping> portAndPhysicalSlotList = entry.getValue();
+            if (portAndPhysicalSlotList.size() > 1) {
+                // duplicate pair of portIndex and physicalSlotIndex found
+                return false;
+            }
+        }
+        return true;
+    }
+    /**
+     * Maps the logical slots to physical slots and ports. Mapping is specified from
+     * {@link UiccSlotMapping} which consist of both physical slot index and port index.
+     * Logical slot is the slot that is seen by modem. Physical slot is the actual physical slot.
+     * Port index is the index (enumerated value) for the associated port available on the SIM.
+     * Each physical slot can have multiple ports if multi-enabled profile(MEP) is supported.
+     *
+     * Example: no. of logical slots 1 and physical slots 2 do not support MEP, each physical slot
+     * has one port:
+     * The only logical slot (index 0) can be mapped to first physical slot (value 0), port(index
+     * 0) or
+     * second physical slot(value 1), port (index 0), while the other physical slot remains unmapped
+     * and inactive.
+     * slotMapping[0] = UiccSlotMapping{0 //logical slot, 0 //physical slot//, 0 //port//}
+     * slotMapping[0] = UiccSlotMapping{1 // logical slot, 1 //physical slot//, 0 //port//}
+     *
+     * Example no. of logical slots 2 and physical slots 2 supports MEP with 2 ports available:
+     * Each logical slot must be mapped to a port (physical slot and port combination).
+     * First logical slot (index 0) can be mapped to physical slot 1 and the second logical slot
+     * can be mapped to either port from physical slot 2.
+     *
+     * slotMapping[0] = UiccSlotMapping{0, 0, 0} and slotMapping[1] = UiccSlotMapping{1, 0, 0} or
+     * slotMapping[0] = UiccSlotMapping{0, 0, 0} and slotMapping[1] = UiccSlotMapping{1, 1, 1}
+     *
+     * or the other way around, the second logical slot(index 1) can be mapped to physical slot 1
+     * and the first logical slot can be mapped to either port from physical slot 2.
+     *
+     * slotMapping[1] = UiccSlotMapping{0, 0, 0} and slotMapping[0] = UiccSlotMapping{1, 0, 0} or
+     * slotMapping[1] = UiccSlotMapping{0, 0, 0} and slotMapping[0] = UiccSlotMapping{1, 1, 1}
+     *
+     * another possible mapping is each logical slot maps to each port of physical slot 2 and there
+     * is no active logical modem mapped to physical slot 1.
+     *
+     * slotMapping[0] = UiccSlotMapping{1, 0, 0} and slotMapping[1] = UiccSlotMapping{1, 1, 1} or
+     * slotMapping[0] = UiccSlotMapping{1, 1, 1} and slotMapping[1] = UiccSlotMapping{1, 0, 0}
+     *
+     * @param slotMapping Logical to physical slot and port mapping.
+     * @throws IllegalStateException if telephony service is null or slot mapping was sent when the
+     *         radio in middle of a silent restart or other invalid states to handle the command
+     * @throws IllegalArgumentException if the caller passes in an invalid collection of
+     *         UiccSlotMapping like duplicate data, etc
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+    public void setSimSlotMapping(@NonNull Collection<UiccSlotMapping> slotMapping) {
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                if (isSlotMappingValid(slotMapping)) {
+                    boolean result = telephony.setSimSlotMapping(new ArrayList(slotMapping));
+                    if (!result) {
+                        throw new IllegalStateException("setSimSlotMapping has failed");
+                    }
+                } else {
+                    throw new IllegalArgumentException("Duplicate UiccSlotMapping data found");
+                }
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    /**
      * Get the mapping from logical slots to physical slots. The key of the map is the logical slot
      * id and the value is the physical slots id mapped to this logical slot id.
      *
@@ -4032,18 +4203,21 @@
      * should be {@link #getPhoneCount()} if success, otherwise return an empty map.
      *
      * @hide
+     * @deprecated use {@link #getSimSlotMapping()} instead.
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     @NonNull
+    @Deprecated
     public Map<Integer, Integer> getLogicalToPhysicalSlotMapping() {
         Map<Integer, Integer> slotMapping = new HashMap<>();
         try {
             ITelephony telephony = getITelephony();
             if (telephony != null) {
-                int[] slotMappingArray = telephony.getSlotsMapping();
-                for (int i = 0; i < slotMappingArray.length; i++) {
-                    slotMapping.put(i, slotMappingArray[i]);
+                List<UiccSlotMapping> simSlotsMapping = telephony.getSlotsMapping(
+                        mContext.getOpPackageName());
+                for (UiccSlotMapping slotMap : simSlotsMapping) {
+                    slotMapping.put(slotMap.getLogicalSlotIndex(), slotMap.getPhysicalSlotIndex());
                 }
             }
         } catch (RemoteException e) {
@@ -4052,6 +4226,33 @@
         return slotMapping;
     }
 
+    /**
+     * Get the mapping from logical slots to physical sim slots and port indexes. Initially the
+     * logical slot index was mapped to physical slot index, but with support for multi-enabled
+     * profile(MEP) logical slot is now mapped to port index.
+     *
+     * @return a collection of {@link UiccSlotMapping} which indicates the mapping from logical
+     *         slots to ports and physical slots.
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    @NonNull
+    public Collection<UiccSlotMapping> getSimSlotMapping() {
+        List<UiccSlotMapping> slotMap = new ArrayList<>();
+        try {
+            ITelephony telephony = getITelephony();
+            if (telephony != null) {
+                slotMap = telephony.getSlotsMapping(mContext.getOpPackageName());
+            } else {
+                throw new IllegalStateException("telephony service is null.");
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+        return slotMap;
+    }
     //
     //
     // Subscriber Info
@@ -4680,7 +4881,10 @@
      *     for any API level.
      *     {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
      *     for apps targeting SDK API level 29 and below.
+     *
+     * @deprecated use {@link SubscriptionManager#getPhoneNumber(int)} instead.
      */
+    @Deprecated
     @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges or default SMS app
     @RequiresPermission(anyOf = {
             android.Manifest.permission.READ_PHONE_STATE,
@@ -4753,7 +4957,9 @@
      * @param alphaTag alpha-tagging of the dailing nubmer
      * @param number The dialing number
      * @return true if the operation was executed correctly.
+     * @deprecated use {@link SubscriptionManager#setCarrierPhoneNumber(int, String)} instead.
      */
+    @Deprecated
     public boolean setLine1NumberForDisplay(String alphaTag, String number) {
         return setLine1NumberForDisplay(getSubId(), alphaTag, number);
     }
@@ -4774,6 +4980,10 @@
      */
     public boolean setLine1NumberForDisplay(int subId, String alphaTag, String number) {
         try {
+            // This API is deprecated; call the new API to allow smooth migartion.
+            // The new API doesn't accept null so convert null to empty string.
+            mSubscriptionManager.setCarrierPhoneNumber(subId, (number == null ? "" : number));
+
             ITelephony telephony = getITelephony();
             if (telephony != null)
                 return telephony.setLine1NumberForDisplayForSubscriber(subId, alphaTag, number);
diff --git a/telephony/java/android/telephony/UiccCardInfo.java b/telephony/java/android/telephony/UiccCardInfo.java
index b4389203..0dfab18 100644
--- a/telephony/java/android/telephony/UiccCardInfo.java
+++ b/telephony/java/android/telephony/UiccCardInfo.java
@@ -20,21 +20,27 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 
 /**
  * The UiccCardInfo represents information about a currently inserted UICC or embedded eUICC.
  */
 public final class UiccCardInfo implements Parcelable {
-
     private final boolean mIsEuicc;
     private final int mCardId;
     private final String mEid;
     private final String mIccId;
-    private final int mSlotIndex;
+    private final int mPhysicalSlotIndex;
     private final boolean mIsRemovable;
+    private final boolean mIsMultipleEnabledProfilesSupported;
+    private final List<UiccPortInfo> mPortList;
+    private boolean mIccIdAccessRestricted = false;
 
-    public static final @android.annotation.NonNull Creator<UiccCardInfo> CREATOR = new Creator<UiccCardInfo>() {
+    public static final @NonNull Creator<UiccCardInfo> CREATOR = new Creator<UiccCardInfo>() {
         @Override
         public UiccCardInfo createFromParcel(Parcel in) {
             return new UiccCardInfo(in);
@@ -47,22 +53,29 @@
     };
 
     private UiccCardInfo(Parcel in) {
-        mIsEuicc = in.readByte() != 0;
+        mIsEuicc = in.readBoolean();
         mCardId = in.readInt();
-        mEid = in.readString();
-        mIccId = in.readString();
-        mSlotIndex = in.readInt();
-        mIsRemovable = in.readByte() != 0;
+        mEid = in.readString8();
+        mIccId = in.readString8();
+        mPhysicalSlotIndex = in.readInt();
+        mIsRemovable = in.readBoolean();
+        mIsMultipleEnabledProfilesSupported = in.readBoolean();
+        mPortList = new ArrayList<UiccPortInfo>();
+        in.readTypedList(mPortList, UiccPortInfo.CREATOR);
+        mIccIdAccessRestricted = in.readBoolean();
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeByte((byte) (mIsEuicc ? 1 : 0));
+        dest.writeBoolean(mIsEuicc);
         dest.writeInt(mCardId);
-        dest.writeString(mEid);
-        dest.writeString(mIccId);
-        dest.writeInt(mSlotIndex);
-        dest.writeByte((byte) (mIsRemovable ? 1 : 0));
+        dest.writeString8(mEid);
+        dest.writeString8(mIccId);
+        dest.writeInt(mPhysicalSlotIndex);
+        dest.writeBoolean(mIsRemovable);
+        dest.writeBoolean(mIsMultipleEnabledProfilesSupported);
+        dest.writeTypedList(mPortList, flags);
+        dest.writeBoolean(mIccIdAccessRestricted);
     }
 
     @Override
@@ -71,20 +84,34 @@
     }
 
     /**
+     * Construct a UiccCardInfo.
+     *
+     * @param isEuicc is a flag to check is eUICC or not
+     * @param cardId is unique ID used to identify a UiccCard.
+     * @param eid is unique eUICC Identifier
+     * @param physicalSlotIndex is unique index referring to a physical SIM slot.
+     * @param isRemovable is a flag to check is removable or embedded
+     * @param isMultipleEnabledProfilesSupported is a flag to check is MEP enabled or not
+     * @param portList has the information regarding port, ICCID and its active status
+     *
      * @hide
      */
-    public UiccCardInfo(boolean isEuicc, int cardId, String eid, String iccId, int slotIndex,
-            boolean isRemovable) {
+    public UiccCardInfo(boolean isEuicc, int cardId, String eid, int physicalSlotIndex,
+            boolean isRemovable, boolean isMultipleEnabledProfilesSupported,
+            @NonNull List<UiccPortInfo> portList) {
         this.mIsEuicc = isEuicc;
         this.mCardId = cardId;
         this.mEid = eid;
-        this.mIccId = iccId;
-        this.mSlotIndex = slotIndex;
+        this.mIccId = null;
+        this.mPhysicalSlotIndex = physicalSlotIndex;
         this.mIsRemovable = isRemovable;
+        this.mIsMultipleEnabledProfilesSupported = isMultipleEnabledProfilesSupported;
+        this.mPortList = portList;
     }
 
     /**
      * Return whether the UICC is an eUICC.
+     *
      * @return true if the UICC is an eUICC.
      */
     public boolean isEuicc() {
@@ -119,40 +146,85 @@
      * <p>
      * Note that this field may be omitted if the caller does not have the correct permissions
      * (see {@link TelephonyManager#getUiccCardsInfo()}).
+     *
+     * @deprecated with support for MEP(multiple enabled profile), a SIM card can have more than one
+     * ICCID active at the same time.Instead use {@link UiccPortInfo#getIccId()} to retrieve ICCID.
+     * To find {@link UiccPortInfo} use {@link UiccCardInfo#getPorts()}
+     *
+     * @throws UnsupportedOperationException if the calling app's target SDK is T and beyond.
      */
     @Nullable
+    @Deprecated
     public String getIccId() {
-        return mIccId;
+        // Temporarily bypassing exception
+        // TODO: add exception once refactoring completed.
+        //if (mIccIdAccessRestricted) {
+        //    throw new UnsupportedOperationException("getIccId from UiccPortInfo");
+        //}
+        //always return ICCID from first port.
+        return getPorts().stream().findFirst().get().getIccId();
     }
 
     /**
      * Gets the slot index for the slot that the UICC is currently inserted in.
+     *
+     * @deprecated use {@link #getPhysicalSlotIndex()}
      */
+    @Deprecated
     public int getSlotIndex() {
-        return mSlotIndex;
+        return mPhysicalSlotIndex;
     }
 
     /**
-     * Returns a copy of the UiccCardinfo with the EID and ICCID set to null. These values are
-     * generally private and require carrier privileges to view.
-     *
-     * @hide
+     * Gets the physical slot index for the slot that the UICC is currently inserted in.
      */
-    @NonNull
-    public UiccCardInfo getUnprivileged() {
-        return new UiccCardInfo(mIsEuicc, mCardId, null, null, mSlotIndex, mIsRemovable);
+    public int getPhysicalSlotIndex() {
+        return mPhysicalSlotIndex;
     }
 
     /**
      * Return whether the UICC or eUICC is removable.
      * <p>
      * UICCs are generally removable, but eUICCs may be removable or built in to the device.
+     *
      * @return true if the UICC or eUICC is removable
      */
     public boolean isRemovable() {
         return mIsRemovable;
     }
 
+    /*
+     * Whether the UICC card supports multiple enable profile(MEP)
+     * UICCs are generally MEP disabled, there can be only one active profile on the physical
+     * sim card.
+     *
+     * @return {@code true} if the eUICC is supporting multiple enabled profile(MEP).
+     */
+    public boolean isMultipleEnabledProfilesSupported() {
+        return mIsMultipleEnabledProfilesSupported;
+    }
+
+    /**
+     * Get information regarding port, ICCID and its active status.
+     *
+     * @return Collection of {@link UiccPortInfo}
+     */
+    public @NonNull Collection<UiccPortInfo> getPorts() {
+        return Collections.unmodifiableList(mPortList);
+    }
+
+    /**
+     * if the flag is set to {@code true} the calling app is not allowed to access deprecated
+     * {@link #getIccId()}
+     * @param iccIdAccessRestricted is the flag to check if app is allowed to access ICCID
+     *
+     * @hide
+     */
+    public void setIccIdAccessRestricted(boolean iccIdAccessRestricted) {
+        this.mIccIdAccessRestricted = iccIdAccessRestricted;
+    }
+
+
     @Override
     public boolean equals(Object obj) {
         if (this == obj) {
@@ -167,13 +239,16 @@
                 && (mCardId == that.mCardId)
                 && (Objects.equals(mEid, that.mEid))
                 && (Objects.equals(mIccId, that.mIccId))
-                && (mSlotIndex == that.mSlotIndex)
-                && (mIsRemovable == that.mIsRemovable));
+                && (mPhysicalSlotIndex == that.mPhysicalSlotIndex)
+                && (mIsRemovable == that.mIsRemovable)
+                && (mIsMultipleEnabledProfilesSupported == that.mIsMultipleEnabledProfilesSupported)
+                && (Objects.equals(mPortList, that.mPortList)));
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mIsEuicc, mCardId, mEid, mIccId, mSlotIndex, mIsRemovable);
+        return Objects.hash(mIsEuicc, mCardId, mEid, mIccId, mPhysicalSlotIndex, mIsRemovable,
+                mIsMultipleEnabledProfilesSupported, mPortList);
     }
 
     @Override
@@ -185,11 +260,17 @@
                 + ", mEid="
                 + mEid
                 + ", mIccId="
-                + mIccId
-                + ", mSlotIndex="
-                + mSlotIndex
+                + SubscriptionInfo.givePrintableIccid(mIccId)
+                + ", mPhysicalSlotIndex="
+                + mPhysicalSlotIndex
                 + ", mIsRemovable="
                 + mIsRemovable
+                + ", mIsMultipleEnabledProfilesSupported="
+                + mIsMultipleEnabledProfilesSupported
+                + ", mPortList="
+                + mPortList
+                + ", mIccIdAccessRestricted="
+                + mIccIdAccessRestricted
                 + ")";
     }
-}
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt b/telephony/java/android/telephony/UiccPortInfo.aidl
similarity index 77%
copy from packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
copy to telephony/java/android/telephony/UiccPortInfo.aidl
index bacc66b..7fff4ba 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
+++ b/telephony/java/android/telephony/UiccPortInfo.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.flags
+package android.telephony;
 
-interface FlagWriter {
-    fun setEnabled(key: Int, value: Boolean) {}
-}
\ No newline at end of file
+parcelable UiccPortInfo;
diff --git a/telephony/java/android/telephony/UiccPortInfo.java b/telephony/java/android/telephony/UiccPortInfo.java
new file mode 100644
index 0000000..d1838c0
--- /dev/null
+++ b/telephony/java/android/telephony/UiccPortInfo.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2021 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 android.telephony;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * UiccPortInfo class represents information about a single port contained on {@link UiccCardInfo}.
+ * Per GSMA SGP.22 V3.0, a port is a logical entity to which an active UICC profile can be bound on
+ * a UICC card. If UICC supports 2 ports, then the port index is numbered 0,1.
+ * Each port index is unique within an UICC, but not necessarily unique across UICC’s.
+ * For UICC's does not support MEP(Multi-enabled profile), just return the default port index 0.
+ */
+public final class UiccPortInfo implements Parcelable{
+    private final String mIccId;
+    private final int mPortIndex;
+    private final int mLogicalSlotIndex;
+    private final boolean mIsActive;
+
+    /**
+     * A redacted String if caller does not have permission to read ICCID.
+     */
+    public static final String ICCID_REDACTED = "FFFFFFFFFFFFFFFFFFFF";
+
+    public static final @NonNull Creator<UiccPortInfo> CREATOR =
+            new Creator<UiccPortInfo>() {
+                @Override
+                public UiccPortInfo createFromParcel(Parcel in) {
+                    return new UiccPortInfo(in);
+                }
+                @Override
+                public UiccPortInfo[] newArray(int size) {
+                    return new UiccPortInfo[size];
+                }
+            };
+
+    private UiccPortInfo(Parcel in) {
+        mIccId = in.readString8();
+        mPortIndex = in.readInt();
+        mLogicalSlotIndex = in.readInt();
+        mIsActive = in.readBoolean();
+    }
+
+    @Override
+    public void writeToParcel(@Nullable Parcel dest, int flags) {
+        dest.writeString8(mIccId);
+        dest.writeInt(mPortIndex);
+        dest.writeInt(mLogicalSlotIndex);
+        dest.writeBoolean(mIsActive);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Construct a UiccPortInfo.
+     *
+     * @param iccId The ICCID of the profile.
+     * @param portIndex The port index is an enumeration of the ports available on the UICC.
+     * @param logicalSlotIndex is unique index referring to a logical SIM slot.
+     * @param isActive is flag to check if port was tied to a modem stack.
+     *
+     * @hide
+     */
+    public UiccPortInfo(String iccId, int portIndex, int logicalSlotIndex, boolean isActive) {
+        this.mIccId = iccId;
+        this.mPortIndex = portIndex;
+        this.mLogicalSlotIndex = logicalSlotIndex;
+        this.mIsActive = isActive;
+    }
+
+    /**
+     * Get the ICCID of the profile associated with this port.
+     * If this port is not {@link #isActive()}, returns {@code null}.
+     * If the caller does not have access to the ICCID for this port, it will be redacted and
+     * {@link #ICCID_REDACTED} will be returned.
+     */
+    public @Nullable String getIccId() {
+        return mIccId;
+    }
+
+    /**
+     * The port index is an enumeration of the ports available on the UICC.
+     * Example: if eUICC1 supports 2 ports, then the port index is numbered 0,1.
+     * Each port index is unique within an UICC, but not necessarily unique across UICC’s.
+     * For UICC's does not support MEP(Multi-enabled profile), just return the default port index 0.
+     */
+    @IntRange(from = 0)
+    public int getPortIndex() {
+        return mPortIndex;
+    }
+
+    /**
+     * @return {@code true} if port was tied to a modem stack.
+     */
+    public boolean isActive() {
+        return mIsActive;
+    }
+
+    /**
+     * Gets logical slot index for the slot that the UICC is currently attached.
+     * Logical slot index or ID: unique index referring to a logical SIM slot.
+     * Logical slot IDs start at 0 and go up depending on the number of supported active slots on
+     * a device.
+     * For example, a dual-SIM device typically has slot 0 and slot 1.
+     * If a device has multiple physical slots but only supports one active slot,
+     * it will have only the logical slot ID 0.
+     *
+     * @return the logical slot index for UICC port, if there is no logical slot index it returns
+     * {@link SubscriptionManager#INVALID_SIM_SLOT_INDEX}
+     */
+    @IntRange(from = 0)
+    public int getLogicalSlotIndex() {
+        return mLogicalSlotIndex;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+
+        UiccPortInfo that = (UiccPortInfo) obj;
+        return (Objects.equals(mIccId, that.mIccId))
+                && (mPortIndex == that.mPortIndex)
+                && (mLogicalSlotIndex == that.mLogicalSlotIndex)
+                && (mIsActive == that.mIsActive);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mIccId, mPortIndex, mLogicalSlotIndex, mIsActive);
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return "UiccPortInfo (isActive="
+                + mIsActive
+                + ", iccId="
+                + SubscriptionInfo.givePrintableIccid(mIccId)
+                + ", portIndex="
+                + mPortIndex
+                + ", mLogicalSlotIndex="
+                + mLogicalSlotIndex
+                + ")";
+    }
+}
diff --git a/telephony/java/android/telephony/UiccSlotInfo.java b/telephony/java/android/telephony/UiccSlotInfo.java
index a0e949a..a8668e7 100644
--- a/telephony/java/android/telephony/UiccSlotInfo.java
+++ b/telephony/java/android/telephony/UiccSlotInfo.java
@@ -24,6 +24,10 @@
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
 import java.util.Objects;
 
 /**
@@ -64,8 +68,10 @@
     private final int mLogicalSlotIdx;
     private final boolean mIsExtendedApduSupported;
     private final boolean mIsRemovable;
+    private final List<UiccPortInfo> mPortList;
+    private boolean mLogicalSlotAccessRestricted = false;
 
-    public static final @android.annotation.NonNull Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() {
+    public static final @NonNull Creator<UiccSlotInfo> CREATOR = new Creator<UiccSlotInfo>() {
         @Override
         public UiccSlotInfo createFromParcel(Parcel in) {
             return new UiccSlotInfo(in);
@@ -78,24 +84,29 @@
     };
 
     private UiccSlotInfo(Parcel in) {
-        mIsActive = in.readByte() != 0;
-        mIsEuicc = in.readByte() != 0;
-        mCardId = in.readString();
+        mIsActive = in.readBoolean();
+        mIsEuicc = in.readBoolean();
+        mCardId = in.readString8();
         mCardStateInfo = in.readInt();
         mLogicalSlotIdx = in.readInt();
-        mIsExtendedApduSupported = in.readByte() != 0;
-        mIsRemovable = in.readByte() != 0;
+        mIsExtendedApduSupported = in.readBoolean();
+        mIsRemovable = in.readBoolean();
+        mPortList = new ArrayList<UiccPortInfo>();
+        in.readTypedList(mPortList, UiccPortInfo.CREATOR);
+        mLogicalSlotAccessRestricted = in.readBoolean();
     }
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeByte((byte) (mIsActive ? 1 : 0));
-        dest.writeByte((byte) (mIsEuicc ? 1 : 0));
-        dest.writeString(mCardId);
+        dest.writeBoolean(mIsActive);
+        dest.writeBoolean(mIsEuicc);
+        dest.writeString8(mCardId);
         dest.writeInt(mCardStateInfo);
         dest.writeInt(mLogicalSlotIdx);
-        dest.writeByte((byte) (mIsExtendedApduSupported ? 1 : 0));
-        dest.writeByte((byte) (mIsRemovable ? 1 : 0));
+        dest.writeBoolean(mIsExtendedApduSupported);
+        dest.writeBoolean(mIsRemovable);
+        dest.writeTypedList(mPortList, flags);
+        dest.writeBoolean(mLogicalSlotAccessRestricted);
     }
 
     @Override
@@ -117,25 +128,44 @@
         this.mLogicalSlotIdx = logicalSlotIdx;
         this.mIsExtendedApduSupported = isExtendedApduSupported;
         this.mIsRemovable = false;
+        this.mPortList = null;
     }
 
     /**
+     * Construct a UiccSlotInfo.
      * @hide
      */
-    public UiccSlotInfo(boolean isActive, boolean isEuicc, String cardId,
-            @CardStateInfo int cardStateInfo, int logicalSlotIdx, boolean isExtendedApduSupported,
-            boolean isRemovable) {
-        this.mIsActive = isActive;
+    public UiccSlotInfo(boolean isEuicc, String cardId,
+            @CardStateInfo int cardStateInfo, boolean isExtendedApduSupported,
+            boolean isRemovable, @NonNull List<UiccPortInfo> portList) {
+        this.mIsActive = portList.get(0).isActive();
         this.mIsEuicc = isEuicc;
         this.mCardId = cardId;
         this.mCardStateInfo = cardStateInfo;
-        this.mLogicalSlotIdx = logicalSlotIdx;
+        this.mLogicalSlotIdx = portList.get(0).getLogicalSlotIndex();
         this.mIsExtendedApduSupported = isExtendedApduSupported;
         this.mIsRemovable = isRemovable;
+        this.mPortList = portList;
     }
 
+    /**
+     * @deprecated There is no longer isActive state for each slot because ports belonging
+     * to the physical slot could have different states
+     * we instead use {@link UiccPortInfo#isActive()}
+     * To get UiccPortInfo use {@link UiccSlotInfo#getPorts()}
+     *
+     * @return {@code true} if status is active.
+     * @throws UnsupportedOperationException if the calling app's target SDK is T and beyond.
+     */
+    @Deprecated
     public boolean getIsActive() {
-        return mIsActive;
+        // Temporarily bypassing exception
+        // TODO: add exception once refactoring completed.
+        //if (mLogicalSlotAccessRestricted) {
+        //    throw new UnsupportedOperationException("get port status from UiccPortInfo");
+        //}
+        //always return status from first port.
+        return getPorts().stream().findFirst().get().isActive();
     }
 
     public boolean getIsEuicc() {
@@ -159,8 +189,23 @@
         return mCardStateInfo;
     }
 
+    /**
+     * @deprecated There is no longer getLogicalSlotIndex
+     * There is no longer getLogicalSlotIdx as each port belonging to this physical slot could have
+     * different logical slot index. Use {@link UiccPortInfo#getLogicalSlotIndex()} instead
+     *
+     * @throws UnsupportedOperationException if the calling app's target SDK is T and beyond.
+     */
+    @Deprecated
     public int getLogicalSlotIdx() {
-        return mLogicalSlotIdx;
+        // Temporarily bypassing exception
+        // TODO: add exception once refactoring completed.
+        //if (mLogicalSlotAccessRestricted) {
+        //    throw new UnsupportedOperationException("get logical slot index from UiccPortInfo");
+        //}
+        //always return logical slot index from first port.
+        //portList always have at least one element.
+        return getPorts().stream().findFirst().get().getLogicalSlotIndex();
     }
 
     /**
@@ -170,16 +215,37 @@
         return mIsExtendedApduSupported;
     }
 
-   /**
+    /**
      * Return whether the UICC slot is for a removable UICC.
      * <p>
      * UICCs are generally removable, but eUICCs may be removable or built in to the device.
+     *
      * @return true if the slot is for removable UICCs
      */
     public boolean isRemovable() {
         return mIsRemovable;
     }
 
+    /**
+     * Get Information regarding port, iccid and its active status.
+     *
+     * @return Collection of {@link UiccPortInfo}
+     */
+    public @NonNull Collection<UiccPortInfo> getPorts() {
+        return Collections.unmodifiableList(mPortList);
+    }
+
+    /**
+     * Set the flag to check compatibility of the calling app's target SDK is T and beyond.
+     *
+     * @param logicalSlotAccessRestricted is the flag to check compatibility.
+     *
+     * @hide
+     */
+    public void setLogicalSlotAccessRestricted(boolean logicalSlotAccessRestricted) {
+        this.mLogicalSlotAccessRestricted = logicalSlotAccessRestricted;
+    }
+
     @Override
     public boolean equals(@Nullable Object obj) {
         if (this == obj) {
@@ -196,20 +262,14 @@
                 && (mCardStateInfo == that.mCardStateInfo)
                 && (mLogicalSlotIdx == that.mLogicalSlotIdx)
                 && (mIsExtendedApduSupported == that.mIsExtendedApduSupported)
-                && (mIsRemovable == that.mIsRemovable);
+                && (mIsRemovable == that.mIsRemovable)
+                && (Objects.equals(mPortList, that.mPortList));
     }
 
     @Override
     public int hashCode() {
-        int result = 1;
-        result = 31 * result + (mIsActive ? 1 : 0);
-        result = 31 * result + (mIsEuicc ? 1 : 0);
-        result = 31 * result + Objects.hashCode(mCardId);
-        result = 31 * result + mCardStateInfo;
-        result = 31 * result + mLogicalSlotIdx;
-        result = 31 * result + (mIsExtendedApduSupported ? 1 : 0);
-        result = 31 * result + (mIsRemovable ? 1 : 0);
-        return result;
+        return Objects.hash(mIsActive, mIsEuicc, mCardId, mCardStateInfo, mLogicalSlotIdx,
+                mIsExtendedApduSupported, mIsRemovable, mPortList);
     }
 
     @NonNull
@@ -229,6 +289,10 @@
                 + mIsExtendedApduSupported
                 + ", mIsRemovable="
                 + mIsRemovable
+                + ", mPortList="
+                + mPortList
+                + ", mLogicalSlotAccessRestricted="
+                + mLogicalSlotAccessRestricted
                 + ")";
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt b/telephony/java/android/telephony/UiccSlotMapping.aidl
similarity index 77%
copy from packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
copy to telephony/java/android/telephony/UiccSlotMapping.aidl
index bacc66b..3b19499 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FlagWriter.kt
+++ b/telephony/java/android/telephony/UiccSlotMapping.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.flags
+package android.telephony;
 
-interface FlagWriter {
-    fun setEnabled(key: Int, value: Boolean) {}
-}
\ No newline at end of file
+parcelable UiccSlotMapping;
diff --git a/telephony/java/android/telephony/UiccSlotMapping.java b/telephony/java/android/telephony/UiccSlotMapping.java
new file mode 100644
index 0000000..87e7acd
--- /dev/null
+++ b/telephony/java/android/telephony/UiccSlotMapping.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2021 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 android.telephony;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * <p>Provides information for a SIM slot mapping, which establishes a unique mapping between a
+ * logical SIM slot and a physical SIM slot and port index.  A logical SIM slot represents a
+ * potentially active SIM slot, where a physical SIM slot and port index represent a hardware SIM
+ * slot and port (capable of having an active profile) which can be mapped to a logical sim slot.
+ * <p>It contains the following parameters:
+ * <ul>
+ * <li>Port index: unique index referring to a port belonging to the physical SIM slot.
+ * If the SIM does not support multiple enabled profiles, the port index is default index 0.</li>
+ * <li>Physical slot index: unique index referring to a physical SIM slot. Physical slot IDs start
+ * at 0 and go up depending on the number of physical slots on the device.
+ * This differs from the number of logical slots a device has, which corresponds to the number of
+ * active slots a device is capable of using. For example, a device which switches between dual-SIM
+ * and single-SIM mode may always have two physical slots, but in single-SIM mode it will have only
+ * one logical slot.</li>
+ * <li>Logical slot index: unique index referring to a logical SIM slot, Logical slot IDs start at 0
+ * and go up depending on the number of supported active slots on a device.
+ * For example, a dual-SIM device typically has slot 0 and slot 1. If a device has multiple physical
+ * slots but only supports one active slot, it will have only the logical slot ID 0</li>
+ * </ul>
+ *
+ * <p> This configurations tells a specific logical slot is mapped to a port from an actual physical
+ * sim slot @see <a href="https://developer.android.com/guide/topics/connectivity/telecom/telephony-ids">the Android Developer Site</a>
+ * for more information.
+ * @hide
+ */
+@SystemApi
+public final class UiccSlotMapping implements Parcelable {
+    private final int mPortIndex;
+    private final int mPhysicalSlotIndex;
+    private final int mLogicalSlotIndex;
+
+    public static final @NonNull Creator<UiccSlotMapping> CREATOR =
+            new Creator<UiccSlotMapping>() {
+        @Override
+        public UiccSlotMapping createFromParcel(Parcel in) {
+            return new UiccSlotMapping(in);
+        }
+
+        @Override
+        public UiccSlotMapping[] newArray(int size) {
+            return new UiccSlotMapping[size];
+        }
+    };
+
+    private UiccSlotMapping(Parcel in) {
+        mPortIndex = in.readInt();
+        mPhysicalSlotIndex = in.readInt();
+        mLogicalSlotIndex = in.readInt();
+    }
+
+    @Override
+    public void writeToParcel(@Nullable Parcel dest, int flags) {
+        dest.writeInt(mPortIndex);
+        dest.writeInt(mPhysicalSlotIndex);
+        dest.writeInt(mLogicalSlotIndex);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     *
+     * @param portIndex The port index is an enumeration of the ports available on the UICC.
+     * @param physicalSlotIndex is unique index referring to a physical SIM slot.
+     * @param logicalSlotIndex is unique index referring to a logical SIM slot.
+     *
+     * @hide
+     */
+    public UiccSlotMapping(int portIndex, int physicalSlotIndex, int logicalSlotIndex) {
+        this.mPortIndex = portIndex;
+        this.mPhysicalSlotIndex = physicalSlotIndex;
+        this.mLogicalSlotIndex = logicalSlotIndex;
+    }
+
+    /**
+     * Port index is the unique index referring to a port belonging to the physical SIM slot.
+     * If the SIM does not support multiple enabled profiles, the port index is default index 0.
+     *
+     * @return port index.
+     */
+    @IntRange(from = 0)
+    public int getPortIndex() {
+        return mPortIndex;
+    }
+
+    /**
+     * Gets the physical slot index for the slot that the UICC is currently inserted in.
+     *
+     * @return physical slot index which is the index of actual physical UICC slot.
+     */
+    @IntRange(from = 0)
+    public int getPhysicalSlotIndex() {
+        return mPhysicalSlotIndex;
+    }
+
+    /**
+     * Gets logical slot index for the slot that the UICC is currently attached.
+     * Logical slot index is the unique index referring to a logical slot(logical modem stack).
+     *
+     * @return logical slot index;
+     */
+    @IntRange(from = 0)
+    public int getLogicalSlotIndex() {
+        return mLogicalSlotIndex;
+    }
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null || getClass() != obj.getClass()) {
+            return false;
+        }
+
+        UiccSlotMapping that = (UiccSlotMapping) obj;
+        return (mPortIndex == that.mPortIndex)
+                && (mPhysicalSlotIndex == that.mPhysicalSlotIndex)
+                && (mLogicalSlotIndex == that.mLogicalSlotIndex);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mPortIndex, mPhysicalSlotIndex, mLogicalSlotIndex);
+    }
+
+    @NonNull
+    @Override
+    public String toString() {
+        return "UiccSlotMapping (mPortIndex="
+                + mPortIndex
+                + ", mPhysicalSlotIndex="
+                + mPhysicalSlotIndex
+                + ", mLogicalSlotIndex="
+                + mLogicalSlotIndex
+                + ")";
+    }
+}
diff --git a/telephony/java/android/telephony/data/DataProfile.java b/telephony/java/android/telephony/data/DataProfile.java
index 93903d2..c1d16a9 100644
--- a/telephony/java/android/telephony/data/DataProfile.java
+++ b/telephony/java/android/telephony/data/DataProfile.java
@@ -18,13 +18,16 @@
 
 import static android.telephony.data.ApnSetting.ProtocolType;
 
+import android.annotation.ElapsedRealtimeLong;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.net.NetworkCapabilities;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.telephony.Annotation.ApnType;
+import android.telephony.Annotation.NetCapability;
 import android.telephony.TelephonyManager;
 import android.telephony.TelephonyManager.NetworkTypeBitMask;
 import android.telephony.data.ApnSetting.AuthType;
@@ -66,7 +69,13 @@
 
     private final @Nullable TrafficDescriptor mTrafficDescriptor;
 
-    private final boolean mPreferred;
+    private boolean mPreferred;
+
+    /**
+     * The last timestamp of this data profile being used for data network setup. Never add this
+     * to {@link #equals(Object)} and {@link #hashCode()}.
+     */
+    private @ElapsedRealtimeLong long mSetupTimestamp;
 
     private DataProfile(@NonNull Builder builder) {
         mApnSetting = builder.mApnSetting;
@@ -99,6 +108,7 @@
         mApnSetting = source.readParcelable(ApnSetting.class.getClassLoader());
         mTrafficDescriptor = source.readParcelable(TrafficDescriptor.class.getClassLoader());
         mPreferred = source.readBoolean();
+        mSetupTimestamp = source.readLong();
     }
 
     /**
@@ -291,6 +301,16 @@
     }
 
     /**
+     * Set the preferred flag for the data profile.
+     *
+     * @param preferred {@code true} if this data profile is preferred for internet.
+     * @hide
+     */
+    public void setPreferred(boolean preferred) {
+        mPreferred = preferred;
+    }
+
+    /**
      * @return {@code true} if this data profile was used to bring up the last default
      * (i.e internet) data connection successfully, or the one chosen by the user in Settings'
      * APN editor. For one carrier there can be only one profiled preferred.
@@ -315,6 +335,94 @@
         return mTrafficDescriptor;
     }
 
+    /**
+     * Check if this data profile can satisfy certain network capabilities
+     *
+     * @param networkCapabilities The network capabilities. Note that the non-APN-type capabilities
+     * will be ignored.
+     *
+     * @return {@code true} if this data profile can satisfy the given network capabilities.
+     * @hide
+     */
+    public boolean canSatisfy(@NonNull @NetCapability int[] networkCapabilities) {
+        if (mApnSetting != null) {
+            for (int netCap : networkCapabilities) {
+                if (!canSatisfy(netCap)) {
+                    return false;
+                }
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Check if this data profile can satisfy a certain network capability.
+     *
+     * @param networkCapability The network capability. Note that the non-APN-type capability
+     * will always be satisfied.
+     * @return {@code true} if this data profile can satisfy the given network capability.
+     * @hide
+     */
+    public boolean canSatisfy(@NetCapability int networkCapability) {
+        return mApnSetting != null && mApnSetting.canHandleType(
+                networkCapabilityToApnType(networkCapability));
+    }
+
+    /**
+     * Convert network capability into APN type.
+     *
+     * @param networkCapability Network capability.
+     * @return APN type.
+     * @hide
+     */
+    private static @ApnType int networkCapabilityToApnType(@NetCapability int networkCapability) {
+        switch (networkCapability) {
+            case NetworkCapabilities.NET_CAPABILITY_MMS:
+                return ApnSetting.TYPE_MMS;
+            case NetworkCapabilities.NET_CAPABILITY_SUPL:
+                return ApnSetting.TYPE_SUPL;
+            case NetworkCapabilities.NET_CAPABILITY_DUN:
+                return ApnSetting.TYPE_DUN;
+            case NetworkCapabilities.NET_CAPABILITY_FOTA:
+                return ApnSetting.TYPE_FOTA;
+            case NetworkCapabilities.NET_CAPABILITY_IMS:
+                return ApnSetting.TYPE_IMS;
+            case NetworkCapabilities.NET_CAPABILITY_CBS:
+                return ApnSetting.TYPE_CBS;
+            case NetworkCapabilities.NET_CAPABILITY_XCAP:
+                return ApnSetting.TYPE_XCAP;
+            case NetworkCapabilities.NET_CAPABILITY_EIMS:
+                return ApnSetting.TYPE_EMERGENCY;
+            case NetworkCapabilities.NET_CAPABILITY_INTERNET:
+                return ApnSetting.TYPE_DEFAULT;
+            case NetworkCapabilities.NET_CAPABILITY_MCX:
+                return ApnSetting.TYPE_MCX;
+            case NetworkCapabilities.NET_CAPABILITY_IA:
+                return ApnSetting.TYPE_IA;
+            default:
+                return ApnSetting.TYPE_NONE;
+        }
+    }
+
+    /**
+     * Set the timestamp of this data profile being used for data network setup.
+     *
+     * @hide
+     */
+    public void setLastSetupTimestamp(@ElapsedRealtimeLong long timestamp) {
+        mSetupTimestamp = timestamp;
+    }
+
+    /**
+     * @return the timestamp of this data profile being used for data network setup.
+     *
+     * @hide
+     */
+    public @ElapsedRealtimeLong long getLastSetupTimestamp() {
+        return mSetupTimestamp;
+    }
+
     @Override
     public int describeContents() {
         return 0;
@@ -323,8 +431,8 @@
     @NonNull
     @Override
     public String toString() {
-        return "DataProfile=" + mApnSetting + ", " + mTrafficDescriptor + ", preferred="
-                + mPreferred;
+        return "[DataProfile=" + mApnSetting + ", " + mTrafficDescriptor + ", preferred="
+                + mPreferred + "]";
     }
 
     @Override
@@ -333,6 +441,7 @@
         dest.writeParcelable(mApnSetting, flags);
         dest.writeParcelable(mTrafficDescriptor, flags);
         dest.writeBoolean(mPreferred);
+        dest.writeLong(mSetupTimestamp);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<DataProfile> CREATOR =
diff --git a/telephony/java/android/telephony/euicc/EuiccCardManager.java b/telephony/java/android/telephony/euicc/EuiccCardManager.java
index e1aec0a..ab35d77 100644
--- a/telephony/java/android/telephony/euicc/EuiccCardManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccCardManager.java
@@ -17,6 +17,7 @@
 
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.content.Context;
@@ -24,6 +25,7 @@
 import android.os.RemoteException;
 import android.service.euicc.EuiccProfileInfo;
 import android.telephony.TelephonyFrameworkInitializer;
+import android.telephony.TelephonyManager;
 import android.util.Log;
 
 import com.android.internal.telephony.euicc.IAuthenticateServerCallback;
@@ -122,7 +124,6 @@
 
     /** Result code indicating the caller is not the active LPA. */
     public static final int RESULT_CALLER_NOT_ALLOWED = -3;
-
     /**
      * Callback to receive the result of an eUICC card API.
      *
@@ -220,12 +221,48 @@
      * @param refresh Whether sending the REFRESH command to modem.
      * @param executor The executor through which the callback should be invoked.
      * @param callback The callback to get the result code.
+     *
+     * @deprecated instead use {@link #disableProfile(String, String, int, boolean, Executor,
+     *             ResultCallback)}
      */
+    @Deprecated
     public void disableProfile(String cardId, String iccid, boolean refresh,
             @CallbackExecutor Executor executor, ResultCallback<Void> callback) {
         try {
             getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid,
-                    refresh, new IDisableProfileCallback.Stub() {
+                    TelephonyManager.DEFAULT_PORT_INDEX, refresh,
+                    new IDisableProfileCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode) {
+                            final long token = Binder.clearCallingIdentity();
+                            try {
+                                executor.execute(() -> callback.onComplete(resultCode, null));
+                            } finally {
+                                Binder.restoreCallingIdentity(token);
+                            }
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling disableProfile", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+    /**
+     * Disables the profile of the given ICCID.
+     *
+     * @param cardId The Id of the eUICC.
+     * @param iccid The iccid of the profile.
+     * @param portIndex the Port index is the unique index referring to a port.
+     * @param refresh Whether sending the REFRESH command to modem.
+     * @param executor The executor through which the callback should be invoked.
+     * @param callback The callback to get the result code.
+     */
+    public void disableProfile(@Nullable String cardId, @Nullable String iccid, int portIndex,
+            boolean refresh, @NonNull @CallbackExecutor Executor executor,
+            @NonNull ResultCallback<Void> callback) {
+        try {
+            getIEuiccCardController().disableProfile(mContext.getOpPackageName(), cardId, iccid,
+                    portIndex, refresh, new IDisableProfileCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode) {
                             final long token = Binder.clearCallingIdentity();
@@ -251,12 +288,51 @@
      * @param refresh Whether sending the REFRESH command to modem.
      * @param executor The executor through which the callback should be invoked.
      * @param callback The callback to get the result code and the EuiccProfileInfo enabled.
+     *
+     * @deprecated instead use {@link #switchToProfile(String, String, int, boolean, Executor,
+     *             ResultCallback)}
      */
+    @Deprecated
     public void switchToProfile(String cardId, String iccid, boolean refresh,
             @CallbackExecutor Executor executor, ResultCallback<EuiccProfileInfo> callback) {
         try {
             getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid,
-                    refresh, new ISwitchToProfileCallback.Stub() {
+                    TelephonyManager.DEFAULT_PORT_INDEX, refresh,
+                    new ISwitchToProfileCallback.Stub() {
+                        @Override
+                        public void onComplete(int resultCode, EuiccProfileInfo profile) {
+                            final long token = Binder.clearCallingIdentity();
+                            try {
+                                executor.execute(() -> callback.onComplete(resultCode, profile));
+                            } finally {
+                                Binder.restoreCallingIdentity(token);
+                            }
+                        }
+                    });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error calling switchToProfile", e);
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Switches from the current profile to another profile. The current profile will be disabled
+     * and the specified profile will be enabled. Here portIndex specifies on which port the
+     * profile is to be enabled.
+     *
+     * @param cardId The Id of the eUICC.
+     * @param iccid The iccid of the profile to switch to.
+     * @param portIndex The Port index is the unique index referring to a port.
+     * @param refresh Whether sending the REFRESH command to modem.
+     * @param executor The executor through which the callback should be invoked.
+     * @param callback The callback to get the result code and the EuiccProfileInfo enabled.
+     */
+    public void switchToProfile(@Nullable String cardId, @Nullable String iccid, int portIndex,
+            boolean refresh, @NonNull @CallbackExecutor Executor executor,
+            @NonNull ResultCallback<EuiccProfileInfo> callback) {
+        try {
+            getIEuiccCardController().switchToProfile(mContext.getOpPackageName(), cardId, iccid,
+                    portIndex, refresh, new ISwitchToProfileCallback.Stub() {
                         @Override
                         public void onComplete(int resultCode, EuiccProfileInfo profile) {
                             final long token = Binder.clearCallingIdentity();
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index 2edb564c..aa514b9 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -16,6 +16,7 @@
 package android.telephony.euicc;
 
 import android.Manifest;
+import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -28,6 +29,7 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.PackageManager;
+import android.os.Binder;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.telephony.TelephonyFrameworkInitializer;
@@ -35,11 +37,13 @@
 import android.telephony.euicc.EuiccCardManager.ResetOption;
 
 import com.android.internal.telephony.euicc.IEuiccController;
+import com.android.internal.telephony.euicc.IResultCallback;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Collections;
 import java.util.List;
+import java.util.concurrent.Executor;
 import java.util.stream.Collectors;
 
 /**
@@ -215,6 +219,20 @@
             "android.telephony.euicc.action.START_EUICC_ACTIVATION";
 
     /**
+     * Result codes passed to the ResultListener by
+     * {@link #switchToSubscription(int, int, Executor, ResultListener)}
+     *
+     * @hide
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"EMBEDDED_SUBSCRIPTION_RESULT_"}, value = {
+            EMBEDDED_SUBSCRIPTION_RESULT_OK,
+            EMBEDDED_SUBSCRIPTION_RESULT_ERROR,
+            EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
+    })
+    public @interface ResultCode{}
+
+    /**
      * Result code for an operation indicating that the operation succeeded.
      */
     public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0;
@@ -1125,7 +1143,12 @@
      *     permission, or the calling app must be authorized to manage the active subscription on
      *     the target eUICC.
      * @param callbackIntent a PendingIntent to launch when the operation completes.
+     *
+     * @deprecated From T, callers should use
+     * {@link #switchToSubscription(int, int, Executor, ResultListener)} instead to specify a port
+     * index on the card to switch to.
      */
+    @Deprecated
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void switchToSubscription(int subscriptionId, PendingIntent callbackIntent) {
         if (!isEnabled()) {
@@ -1141,6 +1164,71 @@
     }
 
     /**
+     * Switch to (enable) the given subscription.
+     *
+     * <p>Requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission,
+     * or the calling app must be authorized to manage both the currently-active subscription and
+     * the subscription to be enabled according to the subscription metadata. Without the former,
+     * an {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
+     * intent to prompt the user to accept the download.
+     *
+     * <p>On a multi-active SIM device, requires the
+     * {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission, or a calling app
+     * only if the targeted eUICC does not currently have an active subscription or the calling app
+     * is authorized to manage the active subscription on the target eUICC, and the calling app is
+     * authorized to manage any active subscription on any SIM. Without it, an
+     * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the callback
+     * intent to prompt the user to accept the download. The caller should also be authorized to
+     * manage the subscription to be enabled.
+     *
+     * @param subscriptionId the ID of the subscription to enable. May be
+     *     {@link android.telephony.SubscriptionManager#INVALID_SUBSCRIPTION_ID} to deactivate the
+     *     current profile without activating another profile to replace it. If it's a disable
+     *     operation, requires the {@code android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS}
+     *     permission, or the calling app must be authorized to manage the active subscription on
+     *     the target eUICC.
+     * @param portIndex the index of the port to target for the enabled subscription
+     * @param executor an Executor on which to run the callback
+     * @param callback a {@link ResultListener} which will run when the operation completes
+     */
+    @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
+    public void switchToSubscription(int subscriptionId, int portIndex,
+            @NonNull @CallbackExecutor Executor executor,
+            @NonNull ResultListener callback) {
+        if (!isEnabled()) {
+            sendUnavailableErrorToCallback(executor, callback);
+            return;
+        }
+        try {
+            IResultCallback internalCallback = new IResultCallback.Stub() {
+                @Override
+                public void onComplete(int result, Intent resultIntent) {
+                    executor.execute(() -> Binder.withCleanCallingIdentity(
+                            () -> callback.onComplete(result, resultIntent)));
+                }
+            };
+            getIEuiccController().switchToSubscriptionWithPort(mCardId, portIndex,
+                    subscriptionId, mContext.getOpPackageName(), internalCallback);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
+     * Callback to receive the result of an EuiccManager API.
+     */
+    public interface ResultListener {
+        /**
+         * Called on completion of some operation.
+         * @param resultCode representing success or specific failure of the operation
+         *                   (See {@link ResultCode})
+         * @param resultIntent an intent used to start a resolution activity when an error
+         *                     occurs that can be resolved by the user
+         */
+        void onComplete(@ResultCode int resultCode, @Nullable Intent resultIntent);
+    }
+
+    /**
      * Update the nickname for the given subscription.
      *
      * <p>Requires that the calling app has carrier privileges according to the metadata of the
@@ -1411,6 +1499,13 @@
         }
     }
 
+    private static void sendUnavailableErrorToCallback(@NonNull Executor executor,
+            ResultListener callback) {
+        Integer result = EMBEDDED_SUBSCRIPTION_RESULT_ERROR;
+        executor.execute(() ->
+                Binder.withCleanCallingIdentity(() -> callback.onComplete(result, null)));
+    }
+
     private static IEuiccController getIEuiccController() {
         return IEuiccController.Stub.asInterface(
                 TelephonyFrameworkInitializer
@@ -1418,4 +1513,22 @@
                         .getEuiccControllerService()
                         .get());
     }
+
+    /**
+     * Returns whether the passing portIndex is available.
+     * A port is available if it has no profiles enabled on it or calling app has carrier privilege
+     * over the profile installed on the selected port.
+     * Always returns false if the cardId is a physical card.
+     *
+     * @param portIndex is an enumeration of the ports available on the UICC.
+     * @return {@code true} if port is available
+     */
+    public boolean isSimPortAvailable(int portIndex) {
+        try {
+            return getIEuiccController().isSimPortAvailable(mCardId, portIndex,
+                    mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/telephony/java/android/telephony/ims/DelegateRegistrationState.java b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
index c00c741..1b10404 100644
--- a/telephony/java/android/telephony/ims/DelegateRegistrationState.java
+++ b/telephony/java/android/telephony/ims/DelegateRegistrationState.java
@@ -117,6 +117,7 @@
     })
     public @interface DeregisteringReason {}
 
+    private ArraySet<String> mRegisteringTags = new ArraySet<>();
     private ArraySet<String> mRegisteredTags = new ArraySet<>();
     private final ArraySet<FeatureTagState> mDeregisteringTags = new ArraySet<>();
     private final ArraySet<FeatureTagState> mDeregisteredTags = new ArraySet<>();
@@ -134,6 +135,20 @@
         }
 
         /**
+         * Add the set of feature tags that are associated with this SipDelegate and
+         * the IMS stack is actively trying to register on the carrier network.
+         *
+         * The feature tags will either move to the registered or deregistered state
+         * depending on the result of the registration.
+         * @param featureTags The IMS media feature tags that are in the progress of registering.
+         * @return The in-progress Builder instance for RegistrationState. ]
+         */
+        public @NonNull Builder addRegisteringFeatureTags(@NonNull Set<String> featureTags) {
+            mState.mRegisteringTags.addAll(featureTags);
+            return this;
+        }
+
+        /**
          * Add a feature tag that is currently included in the current network IMS Registration.
          * @param featureTag The IMS media feature tag included in the current IMS registration.
          * @return The in-progress Builder instance for RegistrationState.
@@ -209,6 +224,17 @@
         mRegisteredTags = (ArraySet<String>) source.readArraySet(null);
         readStateFromParcel(source, mDeregisteringTags);
         readStateFromParcel(source, mDeregisteredTags);
+        mRegisteringTags = (ArraySet<String>) source.readArraySet(null);
+    }
+
+    /**
+     * Get the feature tags that are associated with this SipDelegate that the IMS stack is actively
+     * trying to register on the carrier network.
+     * @return A Set of feature tags associated with this SipDelegate that the IMS service is
+     * currently trying to register on the  carrier network.
+     */
+    public @NonNull Set<String> getRegisteringFeatureTags() {
+        return new ArraySet<>(mRegisteringTags);
     }
 
     /**
@@ -286,6 +312,7 @@
         dest.writeArraySet(mRegisteredTags);
         writeStateToParcel(dest, mDeregisteringTags);
         writeStateToParcel(dest, mDeregisteredTags);
+        dest.writeArraySet(mRegisteringTags);
     }
 
     private void writeStateToParcel(Parcel dest, Set<FeatureTagState> state) {
@@ -311,19 +338,22 @@
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
         DelegateRegistrationState that = (DelegateRegistrationState) o;
-        return mRegisteredTags.equals(that.mRegisteredTags)
+        return mRegisteringTags.equals(that.mRegisteringTags)
+                && mRegisteredTags.equals(that.mRegisteredTags)
                 && mDeregisteringTags.equals(that.mDeregisteringTags)
                 && mDeregisteredTags.equals(that.mDeregisteredTags);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mRegisteredTags, mDeregisteringTags, mDeregisteredTags);
+        return Objects.hash(mRegisteringTags, mRegisteredTags,
+                mDeregisteringTags, mDeregisteredTags);
     }
 
     @Override
     public String toString() {
         return "DelegateRegistrationState{ registered={" + mRegisteredTags
+                + "}, registering={" + mRegisteringTags
                 + "}, deregistering={" + mDeregisteringTags + "}, deregistered={"
                 + mDeregisteredTags + "}}";
     }
diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java
index 7a27ed7..683bb92 100644
--- a/telephony/java/android/telephony/ims/ImsMmTelManager.java
+++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java
@@ -25,6 +25,7 @@
 import android.annotation.SuppressAutoDoc;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.content.Context;
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.ServiceSpecificException;
@@ -215,6 +216,7 @@
         }
     }
 
+    private final Context mContext;
     private final int mSubId;
     private final BinderCacheManager<ITelephony> mBinderCache;
 
@@ -256,6 +258,16 @@
      */
     @VisibleForTesting
     public ImsMmTelManager(int subId, BinderCacheManager<ITelephony> binderCache) {
+        this(null, subId, binderCache);
+    }
+
+    /**
+     * Only visible for testing, use {@link ImsManager#getImsMmTelManager(int)} instead.
+     * @hide
+     */
+    @VisibleForTesting
+    public ImsMmTelManager(Context context, int subId, BinderCacheManager<ITelephony> binderCache) {
+        mContext = context;
         mSubId = subId;
         mBinderCache = binderCache;
     }
@@ -1516,7 +1528,8 @@
 
         try {
             telephony.registerImsStateCallback(
-                    mSubId, ImsFeature.FEATURE_MMTEL, callback.getCallbackBinder());
+                    mSubId, ImsFeature.FEATURE_MMTEL,
+                    callback.getCallbackBinder(), getOpPackageName());
         } catch (ServiceSpecificException e) {
             throw new ImsException(e.getMessage(), e.errorCode);
         } catch (RemoteException | IllegalStateException e) {
@@ -1542,6 +1555,14 @@
         }
     }
 
+    private String getOpPackageName() {
+        if (mContext != null) {
+            return mContext.getOpPackageName();
+        } else {
+            return null;
+        }
+    }
+
     private ITelephony getITelephony() {
         return mBinderCache.getBinder();
     }
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index 42af025..1b047c7 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -572,7 +572,8 @@
 
         try {
             telephony.registerImsStateCallback(
-                    mSubId, ImsFeature.FEATURE_RCS, callback.getCallbackBinder());
+                    mSubId, ImsFeature.FEATURE_RCS,
+                    callback.getCallbackBinder(), mContext.getOpPackageName());
         } catch (ServiceSpecificException e) {
             throw new ImsException(e.getMessage(), e.errorCode);
         } catch (RemoteException | IllegalStateException e) {
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
index 48e3d45..f913df5 100644
--- a/telephony/java/android/telephony/ims/SipDelegateManager.java
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -484,7 +484,8 @@
 
         try {
             telephony.registerImsStateCallback(
-                    mSubId, ImsFeature.FEATURE_RCS, callback.getCallbackBinder());
+                    mSubId, ImsFeature.FEATURE_RCS,
+                    callback.getCallbackBinder(), mContext.getOpPackageName());
         } catch (ServiceSpecificException e) {
             throw new ImsException(e.getMessage(), e.errorCode);
         } catch (RemoteException | IllegalStateException e) {
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 6493772..a900c84 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -304,4 +304,13 @@
     int setDeviceToDeviceStatusSharing(int sharing, int subId);
 
     int setDeviceToDeviceStatusSharingContacts(String contacts, int subscriptionId);
+
+    String getPhoneNumber(int subId, int source,
+            String callingPackage, String callingFeatureId);
+
+    String getPhoneNumberFromFirstAvailableSource(int subId,
+            String callingPackage, String callingFeatureId);
+
+    void setPhoneNumber(int subId, int source, String number,
+            String callingPackage, String callingFeatureId);
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index b3c5d042..6d094cb 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -77,6 +77,7 @@
 
 import android.telephony.UiccCardInfo;
 import android.telephony.UiccSlotInfo;
+import android.telephony.UiccSlotMapping;
 
 /**
  * Interface used to interact with the phone.  Mostly this is used by the
@@ -1729,17 +1730,35 @@
      * @return UiccSlotInfo array.
      * @hide
      */
-    UiccSlotInfo[] getUiccSlotsInfo();
+    UiccSlotInfo[] getUiccSlotsInfo(String callingPackage);
 
     /**
      * Map logicalSlot to physicalSlot, and activate the physicalSlot if it is inactive.
      * @param physicalSlots Index i in the array representing physical slot for phone i. The array
      *        size should be same as getPhoneCount().
+     * @deprecated Use {@link #setSimSlotMapping(in List<UiccSlotMapping> slotMapping)} instead.
      * @return boolean Return true if the switch succeeds, false if the switch fails.
      */
     boolean switchSlots(in int[] physicalSlots);
 
     /**
+     * Maps the logical slots to the SlotPortMapping which consist of both physical slot index and
+     * port index. Logical slot is the slot that is seen by modem. Physical slot is the actual
+     * physical slot. Port index is the index (enumerated value) for the associated port available
+     * on the SIM. Each physical slot can have multiple ports which enables multi-enabled profile
+     * (MEP). If eUICC physical slot supports 2 ports, then the port index is numbered 0,1 and if
+     * eUICC2 supports 4 ports then the port index is numbered 0,1,2,3. Each portId is unique within
+     * a UICC physical slot but not necessarily unique across UICC’s. SEP(Single enabled profile)
+     * eUICC and non-eUICC will only have port Index 0.
+     *
+     * Logical slots that are already mapped to the requested SlotPortMapping are not impacted.
+     * @param slotMapping Index i in the list representing slot mapping for phone i.
+     *
+     * @return {@code true} if the switch succeeds, {@code false} if the switch fails.
+     */
+    boolean setSimSlotMapping(in List<UiccSlotMapping> slotMapping);
+
+    /**
      * Returns whether mobile data roaming is enabled on the subscription with id {@code subId}.
      *
      * @param subId the subscription id
@@ -2115,9 +2134,9 @@
              String callingFeatureId);
 
     /**
-     * Get the mapping from logical slots to physical slots.
+     * Get the mapping from logical slots to port index.
      */
-    int[] getSlotsMapping();
+    List<UiccSlotMapping> getSlotsMapping(String callingPackage);
 
     /**
      * Get the IRadio HAL Version encoded as 100 * MAJOR_VERSION + MINOR_VERSION or -1 if unknown
@@ -2497,7 +2516,8 @@
     /**
      * Register an IMS connection state callback
      */
-    void registerImsStateCallback(int subId, int feature, in IImsStateCallback cb);
+    void registerImsStateCallback(int subId, int feature, in IImsStateCallback cb,
+            in String callingPackage);
 
     /**
      * Unregister an IMS connection state callback
diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java
index 3a99f0e0..f650246 100644
--- a/telephony/java/com/android/internal/telephony/PhoneConstants.java
+++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java
@@ -171,6 +171,8 @@
 
     public static final String SLOT_KEY  = "slot";
 
+    public static final String PORT_KEY = "port";
+
     // FIXME: This is used to pass a subId via intents, we need to look at its usage, which is
     // FIXME: extensive, and see if this should be an array of all active subId's or ...?
     /**
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
index e33f44c..c717c09 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl
@@ -45,10 +45,10 @@
         in IGetAllProfilesCallback callback);
     oneway void getProfile(String callingPackage, String cardId, String iccid,
         in IGetProfileCallback callback);
-    oneway void disableProfile(String callingPackage, String cardId, String iccid, boolean refresh,
-        in IDisableProfileCallback callback);
-    oneway void switchToProfile(String callingPackage, String cardId, String iccid, boolean refresh,
-        in ISwitchToProfileCallback callback);
+    oneway void disableProfile(String callingPackage, String cardId, String iccid, int portIndex,
+            boolean refresh, in IDisableProfileCallback callback);
+    oneway void switchToProfile(String callingPackage, String cardId, String iccid, int portIndex,
+            boolean refresh, in ISwitchToProfileCallback callback);
     oneway void setNickname(String callingPackage, String cardId, String iccid, String nickname,
         in ISetNicknameCallback callback);
     oneway void deleteProfile(String callingPackage, String cardId, String iccid,
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index 35e8a12..7f5982f 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -21,6 +21,9 @@
 import android.os.Bundle;
 import android.telephony.euicc.DownloadableSubscription;
 import android.telephony.euicc.EuiccInfo;
+
+import com.android.internal.telephony.euicc.IResultCallback;
+
 import java.util.List;
 
 /** @hide */
@@ -42,6 +45,8 @@
         in PendingIntent callbackIntent);
     oneway void switchToSubscription(int cardId, int subscriptionId, String callingPackage,
         in PendingIntent callbackIntent);
+    oneway void switchToSubscriptionWithPort(int cardId, int portIndex, int subscriptionId,
+        String callingPackage, in IResultCallback callback);
     oneway void updateSubscriptionNickname(int cardId, int subscriptionId, String nickname,
         String callingPackage, in PendingIntent callbackIntent);
     oneway void eraseSubscriptions(int cardId, in PendingIntent callbackIntent);
@@ -51,4 +56,5 @@
     void setSupportedCountries(boolean isSupported, in List<String> countriesList);
     List<String> getSupportedCountries(boolean isSupported);
     boolean isSupportedCountry(String countryIso);
+    boolean isSimPortAvailable(int cardId, int portIndex, String callingPackage);
 }
diff --git a/core/java/android/window/TaskFragmentAppearedInfo.aidl b/telephony/java/com/android/internal/telephony/euicc/IResultCallback.aidl
similarity index 76%
rename from core/java/android/window/TaskFragmentAppearedInfo.aidl
rename to telephony/java/com/android/internal/telephony/euicc/IResultCallback.aidl
index 3729c09..69f479c 100644
--- a/core/java/android/window/TaskFragmentAppearedInfo.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IResultCallback.aidl
@@ -13,11 +13,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package com.android.internal.telephony.euicc;
 
-package android.window;
+import android.content.Intent;
 
-/**
- * Data object for the TaskFragment info provided when a TaskFragment is presented to an organizer.
- * @hide
- */
-parcelable TaskFragmentAppearedInfo;
+/** @hide */
+oneway interface IResultCallback {
+    void onComplete(int resultCode, in Intent resultIntent);
+}
diff --git a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
index 5b44dba..21c3f76 100644
--- a/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
+++ b/telephony/java/com/android/internal/telephony/uicc/IccUtils.java
@@ -23,6 +23,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.os.Build;
+import android.telephony.UiccPortInfo;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.GsmAlphabet;
@@ -44,8 +45,7 @@
     static final int FPLMN_BYTE_SIZE = 3;
 
     // ICCID used for tests by some OEMs
-    // TODO(b/159354974): Replace the constant here with UiccPortInfo.ICCID_REDACTED once ready
-    private static final String TEST_ICCID = "FFFFFFFFFFFFFFFFFFFF";
+    public static final String TEST_ICCID = UiccPortInfo.ICCID_REDACTED;
 
     // A table mapping from a number to a hex character for fast encoding hex strings.
     private static final char[] HEX_CHARS = {
diff --git a/test-mock/Android.bp b/test-mock/Android.bp
index 0bb6198..22320fd 100644
--- a/test-mock/Android.bp
+++ b/test-mock/Android.bp
@@ -27,9 +27,8 @@
 
 java_sdk_library {
     name: "android.test.mock",
-
-    srcs: [
-        ":android-test-mock-sources",
+    srcs: [":android-test-mock-sources"],
+    api_srcs: [
         // Note: Below are NOT APIs of this library. We only take APIs under
         // the android.test.mock package. They however provide private APIs that
         // android.test.mock APIs references to. We need to have the classes in
@@ -44,15 +43,9 @@
         "app-compat-annotations",
         "unsupportedappusage",
     ],
-
     api_packages: [
         "android.test.mock",
     ],
-    // Only include android.test.mock.* classes. Jarjar rules below removes
-    // classes in other packages like android.content. In order to keep the
-    // list up-to-date, permitted_packages ensures that the library contains
-    // clases under android.test.mock after the jarjar rules are applied.
-    jarjar_rules: "jarjar-rules.txt",
     permitted_packages: [
         "android.test.mock",
     ],
diff --git a/test-mock/jarjar-rules.txt b/test-mock/jarjar-rules.txt
deleted file mode 100644
index 4420a44..0000000
--- a/test-mock/jarjar-rules.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-zap android.accounts.**
-zap android.app.**
-zap android.content.**
-zap android.database.**
-zap android.os.**
-zap android.util.**
-zap android.view.**
diff --git a/tests/AttestationVerificationTest/Android.bp b/tests/AttestationVerificationTest/Android.bp
new file mode 100644
index 0000000..a4741eed
--- /dev/null
+++ b/tests/AttestationVerificationTest/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2021 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 {
+    default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+    name: "AttestationVerificationTest",
+    srcs: [
+        "src/**/*.java",
+        "src/**/*.kt",
+    ],
+    defaults: ["cts_defaults"],
+    manifest: "AndroidManifest.xml",
+    test_config: "AndroidTest.xml",
+    platform_apis: true,
+    certificate: "platform",
+    optimize: {
+        enabled: false,
+    },
+    test_suites: ["device-tests"],
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+    ],
+    static_libs: [
+        "compatibility-device-util-axt",
+        "androidx.test.rules",
+        "androidx.test.ext.junit",
+        "platform-test-annotations",
+    ],
+}
diff --git a/tests/AttestationVerificationTest/AndroidManifest.xml b/tests/AttestationVerificationTest/AndroidManifest.xml
new file mode 100755
index 0000000..c42bde9
--- /dev/null
+++ b/tests/AttestationVerificationTest/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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="android.security.attestationverification">
+
+    <uses-sdk android:minSdkVersion="30" android:targetSdkVersion="30" />
+    <uses-permission android:name="android.permission.USE_ATTESTATION_VERIFICATION_SERVICE" />
+
+    <application>
+        <uses-library android:name="android.test.runner"/>
+        <activity android:name=".SystemAttestationVerificationTest$TestActivity" />
+    </application>
+
+    <!--  self-instrumenting test package. -->
+    <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+         android:targetPackage="android.security.attestationverification">
+    </instrumentation>
+</manifest>
diff --git a/tests/AttestationVerificationTest/AndroidTest.xml b/tests/AttestationVerificationTest/AndroidTest.xml
new file mode 100644
index 0000000..1325760
--- /dev/null
+++ b/tests/AttestationVerificationTest/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+<configuration description="Platform tests for Attestation Verification Framework">
+    <option name="test-tag" value="AttestationVerificationTest" />
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="test-file-name" value="AttestationVerificationTest.apk" />
+    </target_preparer>
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.security.attestationverification" />
+        <option name="hidden-api-checks" value="false" />
+    </test>
+</configuration>
diff --git a/tests/AttestationVerificationTest/OWNERS b/tests/AttestationVerificationTest/OWNERS
new file mode 100644
index 0000000..a7a6ef1
--- /dev/null
+++ b/tests/AttestationVerificationTest/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/security/attestationverification/OWNERS
diff --git a/tests/AttestationVerificationTest/src/android/security/attestationverification/SystemAttestationVerificationTest.kt b/tests/AttestationVerificationTest/src/android/security/attestationverification/SystemAttestationVerificationTest.kt
new file mode 100644
index 0000000..48bfd6f
--- /dev/null
+++ b/tests/AttestationVerificationTest/src/android/security/attestationverification/SystemAttestationVerificationTest.kt
@@ -0,0 +1,90 @@
+package android.security.attestationverification
+
+import android.os.Bundle
+import android.app.Activity
+import androidx.test.ext.junit.rules.ActivityScenarioRule
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import org.junit.Assert.assertThrows
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import com.google.common.truth.Truth.assertThat
+import android.security.attestationverification.AttestationVerificationManager.PROFILE_SELF_TRUSTED
+import android.security.attestationverification.AttestationVerificationManager.TYPE_PUBLIC_KEY
+import android.security.attestationverification.AttestationVerificationManager.RESULT_UNKNOWN
+import java.lang.IllegalArgumentException
+import java.time.Duration
+import java.util.concurrent.CompletableFuture
+import java.util.concurrent.TimeUnit
+
+/** Test for system-defined attestation verifiers. */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class SystemAttestationVerificationTest {
+
+    @get:Rule
+    val rule = ActivityScenarioRule(TestActivity::class.java)
+
+    private lateinit var activity: Activity
+    private lateinit var avm: AttestationVerificationManager
+
+    @Before
+    fun setup() {
+        rule.getScenario().onActivity {
+            avm = it.getSystemService(AttestationVerificationManager::class.java)
+            activity = it
+        }
+    }
+
+    @Test
+    fun verifyAttestation_returnsUnknown() {
+        val future = CompletableFuture<Int>()
+        val profile = AttestationProfile(PROFILE_SELF_TRUSTED)
+        avm.verifyAttestation(profile, TYPE_PUBLIC_KEY, Bundle(), ByteArray(0),
+                activity.mainExecutor) { result, _ ->
+            future.complete(result)
+        }
+
+        assertThat(future.getSoon()).isEqualTo(RESULT_UNKNOWN)
+    }
+
+    @Test
+    fun verifyToken_returnsUnknown() {
+        val future = CompletableFuture<Int>()
+        val profile = AttestationProfile(PROFILE_SELF_TRUSTED)
+        avm.verifyAttestation(profile, TYPE_PUBLIC_KEY, Bundle(), ByteArray(0),
+                activity.mainExecutor) { _, token ->
+            val result = avm.verifyToken(profile, TYPE_PUBLIC_KEY, Bundle(), token, null)
+            future.complete(result)
+        }
+
+        assertThat(future.getSoon()).isEqualTo(RESULT_UNKNOWN)
+    }
+
+    @Test
+    fun verifyToken_tooBigMaxAgeThrows() {
+        val future = CompletableFuture<VerificationToken>()
+        val profile = AttestationProfile(PROFILE_SELF_TRUSTED)
+        avm.verifyAttestation(profile, TYPE_PUBLIC_KEY, Bundle(), ByteArray(0),
+                activity.mainExecutor) { _, token ->
+            future.complete(token)
+        }
+
+        assertThrows(IllegalArgumentException::class.java) {
+            avm.verifyToken(profile, TYPE_PUBLIC_KEY, Bundle(), future.getSoon(),
+                    Duration.ofSeconds(3601))
+        }
+    }
+
+    private fun <T> CompletableFuture<T>.getSoon(): T {
+        return this.get(1, TimeUnit.SECONDS)
+    }
+
+    class TestActivity : Activity() {
+        override fun onCreate(savedInstanceState: Bundle?) {
+            super.onCreate(savedInstanceState)
+        }
+    }
+}
diff --git a/tests/FlickerTests/AndroidTest.xml b/tests/FlickerTests/AndroidTest.xml
index 896ec9a..566c725 100644
--- a/tests/FlickerTests/AndroidTest.xml
+++ b/tests/FlickerTests/AndroidTest.xml
@@ -16,10 +16,6 @@
         <!-- restart launcher to activate TAPL -->
         <option name="run-command" value="setprop ro.test_harness 1 ; am force-stop com.google.android.apps.nexuslauncher" />
     </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.DeviceCleaner">
-        <!-- reboot the device to teardown any crashed tests -->
-        <option name="cleanup-action" value="REBOOT" />
-    </target_preparer>
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true"/>
         <option name="test-file-name" value="FlickerTests.apk"/>
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index 209d1aa..7076a07 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -17,6 +17,7 @@
 
 package com.android.server.wm.flicker.close
 
+import android.platform.test.annotations.Presubmit
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -24,6 +25,8 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group4
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -79,6 +82,33 @@
     @Test
     override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
 
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun launcherLayerReplacesApp() {
+        // This test doesn't work in shell transitions because of b/206086894
+        assumeFalse(isShellTransitionsEnabled)
+        super.launcherLayerReplacesApp()
+    }
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun entireScreenCovered() {
+        // This test doesn't work in shell transitions because of b/206086894
+        assumeFalse(isShellTransitionsEnabled)
+        super.entireScreenCovered()
+    }
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index ac557cf..b5d01ef 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -16,6 +16,7 @@
 
 package com.android.server.wm.flicker.close
 
+import android.platform.test.annotations.Presubmit
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -23,6 +24,8 @@
 import com.android.server.wm.flicker.FlickerTestParameterFactory
 import com.android.server.wm.flicker.annotation.Group4
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -78,6 +81,33 @@
     @Test
     override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
 
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun launcherLayerReplacesApp() {
+        // This test doesn't work in shell transitions because of b/206086894
+        assumeFalse(isShellTransitionsEnabled)
+        super.launcherLayerReplacesApp()
+    }
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun entireScreenCovered() {
+        // This test doesn't work in shell transitions because of b/206086894
+        assumeFalse(isShellTransitionsEnabled)
+        super.entireScreenCovered()
+    }
+
     companion object {
         /**
          * Creates the test configurations.
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
index 3c9ba20..ca735031 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
@@ -17,7 +17,6 @@
 package com.android.server.wm.flicker.close
 
 import android.app.Instrumentation
-import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import androidx.test.filters.FlakyTest
 import androidx.test.platform.app.InstrumentationRegistry
@@ -196,13 +195,13 @@
         testSpec.replacesLayer(testApp.component, LAUNCHER_COMPONENT)
     }
 
-    @Postsubmit
+    @FlakyTest
     @Test
     fun runPresubmitAssertion() {
         flickerRule.checkPresubmitAssertions()
     }
 
-    @Postsubmit
+    @FlakyTest
     @Test
     fun runPostsubmitAssertion() {
         flickerRule.checkPostsubmitAssertions()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
index c7dfbf8..f12e4ae 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
@@ -30,6 +30,7 @@
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.entireScreenCovered
 import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.navBarLayerIsVisible
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsVisible
@@ -37,6 +38,7 @@
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsVisible
 import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -154,7 +156,11 @@
 
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
index 5315da1d..39d2518 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
@@ -17,10 +17,10 @@
 package com.android.server.wm.flicker.ime
 
 import android.app.Instrumentation
+import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import android.view.WindowManagerPolicyConstants
-import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.server.wm.flicker.FlickerBuilderProvider
@@ -34,10 +34,12 @@
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsVisible
 import com.android.server.wm.flicker.entireScreenCovered
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.statusBarLayerIsVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsVisible
 import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -103,7 +105,7 @@
         }
     }
 
-    @FlakyTest(bugId = 190189685)
+    @Postsubmit
     @Test
     fun imeAppWindowBecomesInvisible() {
         testSpec.assertWm {
@@ -115,7 +117,11 @@
 
     @Presubmit
     @Test
-    fun entireScreenCovered() = testSpec.entireScreenCovered()
+    fun entireScreenCovered() {
+        // This test doesn't work in shell transitions because of b/206086894
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.entireScreenCovered()
+    }
 
     @Presubmit
     @Test
@@ -153,7 +159,11 @@
 
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
index d063b69..d975cf4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
@@ -32,10 +32,12 @@
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsVisible
 import com.android.server.wm.flicker.entireScreenCovered
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsVisible
 import com.android.server.wm.traces.common.FlickerComponentName
-import org.junit.Assume
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -119,20 +121,24 @@
     @Presubmit
     @Test
     fun navBarLayerRotatesAndScales() {
-        Assume.assumeFalse(testSpec.isLandscapeOrSeascapeAtStart)
+        assumeFalse(testSpec.isLandscapeOrSeascapeAtStart)
         testSpec.navBarLayerRotatesAndScales()
     }
 
     @FlakyTest
     @Test
     fun navBarLayerRotatesAndScales_Flaky() {
-        Assume.assumeTrue(testSpec.isLandscapeOrSeascapeAtStart)
+        assumeTrue(testSpec.isLandscapeOrSeascapeAtStart)
         testSpec.navBarLayerRotatesAndScales()
     }
 
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
index b589969..61fe02e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
@@ -17,10 +17,10 @@
 package com.android.server.wm.flicker.ime
 
 import android.app.Instrumentation
+import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import android.view.WindowManagerPolicyConstants
-import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.server.wm.flicker.FlickerBuilderProvider
@@ -34,9 +34,11 @@
 import com.android.server.wm.flicker.navBarLayerRotatesAndScales
 import com.android.server.wm.flicker.navBarWindowIsVisible
 import com.android.server.wm.flicker.entireScreenCovered
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsVisible
 import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -104,7 +106,7 @@
     @Test
     fun imeWindowBecomesInvisible() = testSpec.imeWindowBecomesInvisible()
 
-    @FlakyTest
+    @Postsubmit
     @Test
     fun imeAppWindowBecomesInvisible() {
         testSpec.assertWm {
@@ -124,7 +126,11 @@
 
     @Presubmit
     @Test
-    fun entireScreenCovered() = testSpec.entireScreenCovered()
+    fun entireScreenCovered() {
+        // This test doesn't work in shell transitions because of b/206086894
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.entireScreenCovered()
+    }
 
     @Presubmit
     @Test
@@ -146,7 +152,11 @@
 
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
index 7bf0186..1c14916 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
@@ -17,10 +17,10 @@
 package com.android.server.wm.flicker.ime
 
 import android.app.Instrumentation
+import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import android.view.WindowManagerPolicyConstants
-import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.server.wm.flicker.FlickerBuilderProvider
@@ -34,9 +34,11 @@
 import com.android.server.wm.flicker.navBarWindowIsVisible
 import com.android.server.wm.flicker.entireScreenCovered
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.statusBarLayerIsVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsVisible
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -128,7 +130,11 @@
 
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
@@ -138,7 +144,7 @@
         }
     }
 
-    @FlakyTest
+    @Postsubmit
     @Test
     fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
         testSpec.assertWm {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index 5d8a382..84e78ec 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -17,10 +17,10 @@
 package com.android.server.wm.flicker.ime
 
 import android.app.Instrumentation
-import android.os.SystemProperties
 import android.platform.test.annotations.Presubmit
 import android.view.Surface
 import android.view.WindowManagerPolicyConstants
+import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.server.wm.flicker.FlickerBuilderProvider
@@ -37,11 +37,13 @@
 import com.android.server.wm.flicker.navBarWindowIsVisible
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.entireScreenCovered
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.statusBarLayerIsVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsVisible
 import com.android.server.wm.traces.common.FlickerComponentName
-import org.junit.Assume
+import org.junit.Assume.assumeFalse
+import org.junit.Assume.assumeTrue
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -60,8 +62,6 @@
 class ReOpenImeWindowTest(private val testSpec: FlickerTestParameter) {
     private val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
     private val testApp = ImeAppAutoFocusHelper(instrumentation, testSpec.startRotation)
-    private val isShellTransitionsEnabled =
-            SystemProperties.getBoolean("persist.debug.shell_transit", false)
 
     @FlickerBuilderProvider
     fun buildFlicker(): FlickerBuilder {
@@ -101,6 +101,8 @@
     @Presubmit
     @Test
     fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
+        // This test doesn't work in shell transitions because of b/204570898
+        assumeFalse(isShellTransitionsEnabled)
         val component = FlickerComponentName("", "RecentTaskScreenshotSurface")
         testSpec.assertWm {
             this.visibleWindowsShownMoreThanOneConsecutiveEntry(
@@ -114,6 +116,8 @@
     @Presubmit
     @Test
     fun launcherWindowBecomesInvisible() {
+        // This test doesn't work in shell transitions because of b/204574221
+        assumeFalse(isShellTransitionsEnabled)
         testSpec.assertWm {
             this.isAppWindowVisible(LAUNCHER_COMPONENT)
                     .then()
@@ -123,12 +127,16 @@
 
     @Presubmit
     @Test
-    fun imeWindowIsAlwaysVisible() = testSpec.imeWindowIsAlwaysVisible(!isShellTransitionsEnabled)
+    fun imeWindowIsAlwaysVisible() {
+        // This test doesn't work in shell transitions because of b/204570898
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.imeWindowIsAlwaysVisible(!isShellTransitionsEnabled)
+    }
 
     @Presubmit
     @Test
     fun imeAppWindowVisibilityLegacy() {
-        Assume.assumeFalse(isShellTransitionsEnabled)
+        assumeFalse(isShellTransitionsEnabled)
         // the app starts visible in live tile, and stays visible for the duration of entering
         // and exiting overview. However, legacy transitions seem to have a bug which causes
         // everything to restart during the test, so expect the app to disappear and come back.
@@ -143,10 +151,10 @@
         }
     }
 
-    @Presubmit
+    @FlakyTest(bugId = 204570898)
     @Test
     fun imeAppWindowVisibility() {
-        Assume.assumeTrue(isShellTransitionsEnabled)
+        assumeTrue(isShellTransitionsEnabled)
         // the app starts visible in live tile, and stays visible for the duration of entering
         // and exiting overview. Since we log 1x per frame, sometimes the activity visibility
         // and the app visibility are updated together, sometimes not, thus ignore activity
@@ -172,7 +180,7 @@
     @Presubmit
     @Test
     fun imeLayerIsBecomesVisibleLegacy() {
-        Assume.assumeFalse(isShellTransitionsEnabled)
+        assumeFalse(isShellTransitionsEnabled)
         testSpec.assertLayers {
             this.isVisible(FlickerComponentName.IME)
                     .then()
@@ -182,10 +190,10 @@
         }
     }
 
-    @Presubmit
+    @FlakyTest(bugId = 204570898)
     @Test
     fun imeLayerIsBecomesVisible() {
-        Assume.assumeTrue(isShellTransitionsEnabled)
+        assumeTrue(isShellTransitionsEnabled)
         testSpec.assertLayers {
             this.isVisible(FlickerComponentName.IME)
         }
@@ -194,6 +202,8 @@
     @Presubmit
     @Test
     fun appLayerReplacesLauncher() {
+        // This test doesn't work in shell transitions because of b/204574221
+        assumeFalse(isShellTransitionsEnabled)
         testSpec.assertLayers {
             this.isVisible(LAUNCHER_COMPONENT)
                 .then()
@@ -209,7 +219,11 @@
 
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     @Presubmit
     @Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index c4fec7f..fe434268f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -25,7 +25,9 @@
 import com.android.server.wm.flicker.annotation.Group1
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -79,6 +81,15 @@
         }
 
     /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
+    /** {@inheritDoc} */
     @FlakyTest
     @Test
     override fun navBarLayerRotatesAndScales() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index c572e8b..53b5354 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -28,7 +28,9 @@
 import com.android.server.wm.flicker.helpers.reopenAppFromOverview
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.traces.common.WindowManagerConditionsFactory
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -96,14 +98,54 @@
         }
 
     /** {@inheritDoc} */
-    @FlakyTest
+    @Presubmit
     @Test
-    override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
 
     /** {@inheritDoc} */
     @Presubmit
     @Test
-    override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
+    override fun entireScreenCovered() {
+        // This test doesn't work in shell transitions because of b/204570898
+        assumeFalse(isShellTransitionsEnabled)
+        super.entireScreenCovered()
+    }
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun appWindowReplacesLauncherAsTopWindow() {
+        // This test doesn't work in shell transitions because of b/206085788
+        assumeFalse(isShellTransitionsEnabled)
+        super.appWindowReplacesLauncherAsTopWindow()
+    }
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun appLayerReplacesLauncher() {
+        // This test doesn't work in shell transitions because of b/206085788
+        assumeFalse(isShellTransitionsEnabled)
+        super.appLayerReplacesLauncher()
+    }
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
+        // This test doesn't work in shell transitions because of b/206090480
+        assumeFalse(isShellTransitionsEnabled)
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+    }
+
+    /** {@inheritDoc} */
+    @FlakyTest
+    @Test
+    override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
 
     /** {@inheritDoc} */
     @Presubmit
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index bd9d7d7..61fe07a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -28,9 +28,11 @@
 import com.android.server.wm.flicker.annotation.Group1
 import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.helpers.WindowUtils
 import com.android.server.wm.traces.common.FlickerComponentName
 import com.google.common.truth.Truth
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -108,7 +110,7 @@
      * Checks that the app layer doesn't exist at the start of the transition, that it is
      * created (invisible) and becomes visible during the transition
      */
-    @FlakyTest
+    @Postsubmit
     @Test
     fun appLayerBecomesVisible() {
         testSpec.assertLayers {
@@ -167,7 +169,7 @@
     }
 
     /** {@inheritDoc} */
-    @FlakyTest
+    @Postsubmit
     @Test
     override fun statusBarWindowIsVisible() = super.statusBarWindowIsVisible()
 
@@ -188,22 +190,28 @@
     /** {@inheritDoc} */
     @FlakyTest(bugId = 202936526)
     @Test
-    override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
 
     /** {@inheritDoc} */
     @Presubmit
     @Test
     fun statusBarLayerPositionAtEnd() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
         testSpec.assertLayersEnd {
             val display = this.entry.displays.minByOrNull { it.id }
-                ?: throw RuntimeException("There is no display!")
+                ?: error("There is no display!")
             this.visibleRegion(FlickerComponentName.STATUS_BAR)
                 .coversExactly(WindowUtils.getStatusBarPosition(display))
         }
     }
 
     /** {@inheritDoc} */
-    @FlakyTest
+    @Postsubmit
     @Test
     override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
             super.visibleWindowsShownMoreThanOneConsecutiveEntry()
@@ -219,7 +227,7 @@
             super.visibleLayersShownMoreThanOneConsecutiveEntry()
 
     /** {@inheritDoc} */
-    @Postsubmit
+    @FlakyTest
     @Test
     override fun entireScreenCovered() = super.entireScreenCovered()
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index dc7df34..4db01bf 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -25,6 +25,8 @@
 import com.android.server.wm.flicker.annotation.Group1
 import com.android.server.wm.flicker.helpers.setRotation
 import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -83,6 +85,33 @@
         }
 
     /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun appWindowReplacesLauncherAsTopWindow() {
+        // This test doesn't work in shell transitions because of b/206094140
+        assumeFalse(isShellTransitionsEnabled)
+        super.appWindowReplacesLauncherAsTopWindow()
+    }
+
+    /** {@inheritDoc} */
+    @Presubmit
+    @Test
+    override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
+        // This test doesn't work in shell transitions because of b/206094140
+        assumeFalse(isShellTransitionsEnabled)
+        super.visibleLayersShownMoreThanOneConsecutiveEntry()
+    }
+
+    /** {@inheritDoc} */
     @FlakyTest
     @Test
     override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index 5b0372d..0a64939 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -18,6 +18,7 @@
 
 import android.app.Instrumentation
 import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
 import android.platform.test.annotations.RequiresDevice
 import android.view.Surface
 import android.view.WindowManagerPolicyConstants
@@ -133,7 +134,7 @@
     /**
      * Checks that the transition starts with [testApp2] being the top window.
      */
-    @Postsubmit
+    @Presubmit
     @Test
     fun startsWithApp2WindowBeingOnTop() {
         testSpec.assertWmStart {
@@ -284,7 +285,7 @@
     /**
      * Checks that the navbar layer is visible throughout the entire transition.
      */
-    @Postsubmit
+    @Presubmit
     @Test
     fun navBarLayerAlwaysIsVisible() = testSpec.navBarLayerIsVisible()
 
@@ -293,21 +294,21 @@
      *
      * NOTE: This doesn't check that the navbar is visible or not.
      */
-    @Postsubmit
+    @Presubmit
     @Test
     fun navbarIsAlwaysInRightPosition() = testSpec.navBarLayerRotatesAndScales()
 
     /**
      * Checks that the status bar window is visible throughout the entire transition.
      */
-    @Postsubmit
+    @Presubmit
     @Test
     fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsVisible()
 
     /**
      * Checks that the status bar layer is visible throughout the entire transition.
      */
-    @Postsubmit
+    @Presubmit
     @Test
     fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsVisible()
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index 99bc115..5b63376 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -18,6 +18,7 @@
 
 import android.app.Instrumentation
 import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
 import android.platform.test.annotations.RequiresDevice
 import android.view.Surface
 import android.view.WindowManagerPolicyConstants
@@ -298,7 +299,7 @@
     /**
      * Checks that the navbar layer is visible throughout the entire transition.
      */
-    @Postsubmit
+    @Presubmit
     @Test
     fun navBarLayerAlwaysIsVisible() = testSpec.navBarLayerIsVisible()
 
@@ -307,21 +308,21 @@
      *
      * NOTE: This doesn't check that the navbar is visible or not.
      */
-    @Postsubmit
+    @Presubmit
     @Test
     fun navbarIsAlwaysInRightPosition() = testSpec.navBarLayerRotatesAndScales()
 
     /**
      * Checks that the status bar window is visible throughout the entire transition.
      */
-    @Postsubmit
+    @Presubmit
     @Test
     fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsVisible()
 
     /**
      * Checks that the status bar layer is visible throughout the entire transition.
      */
-    @Postsubmit
+    @Presubmit
     @Test
     fun statusBarLayerIsAlwaysVisible() = testSpec.statusBarLayerIsVisible()
 
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index 4a90404..c18798f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -16,7 +16,6 @@
 
 package com.android.server.wm.flicker.rotation
 
-import android.platform.test.annotations.Postsubmit
 import android.platform.test.annotations.Presubmit
 import androidx.test.filters.FlakyTest
 import androidx.test.filters.RequiresDevice
@@ -26,11 +25,13 @@
 import com.android.server.wm.flicker.annotation.Group3
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.SimpleAppHelper
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.rules.WMFlickerServiceRuleForTestSpec
 import com.android.server.wm.flicker.statusBarLayerIsVisible
 import com.android.server.wm.flicker.statusBarLayerRotatesScales
 import com.android.server.wm.flicker.statusBarWindowIsVisible
 import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Rule
 import org.junit.Test
@@ -95,13 +96,13 @@
             }
         }
 
-    @Postsubmit
+    @FlakyTest
     @Test
     fun runPresubmitAssertion() {
         flickerRule.checkPresubmitAssertions()
     }
 
-    @Postsubmit
+    @FlakyTest
     @Test
     fun runPostsubmitAssertion() {
         flickerRule.checkPostsubmitAssertions()
@@ -113,11 +114,16 @@
         flickerRule.checkFlakyAssertions()
     }
 
-    /** {@inheritDoc} */
+    /**
+     * Windows maybe recreated when rotated. Checks that the focus does not change or if it does,
+     * focus returns to [testApp]
+     */
     @FlakyTest(bugId = 190185577)
     @Test
-    override fun focusDoesNotChange() {
-        super.focusDoesNotChange()
+    fun focusChanges() {
+        testSpec.assertEventLog {
+            this.focusChanges(testApp.`package`)
+        }
     }
 
     /**
@@ -161,7 +167,11 @@
      */
     @Presubmit
     @Test
-    fun statusBarLayerRotatesScales() = testSpec.statusBarLayerRotatesScales()
+    fun statusBarLayerRotatesScales() {
+        // This test doesn't work in shell transitions because of b/206753786
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.statusBarLayerRotatesScales()
+    }
 
     /** {@inheritDoc} */
     @FlakyTest
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index ce2347d..d1bdeed 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -129,17 +129,6 @@
     open fun entireScreenCovered() = testSpec.entireScreenCovered()
 
     /**
-     * Checks that the focus doesn't change during animation
-     */
-    @Presubmit
-    @Test
-    open fun focusDoesNotChange() {
-        testSpec.assertEventLog {
-            this.focusDoesNotChange()
-        }
-    }
-
-    /**
      * Checks that [testApp] layer covers the entire screen at the start of the transition
      */
     @Presubmit
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index c55d7af..e44bee6 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -26,8 +26,10 @@
 import com.android.server.wm.flicker.annotation.Group3
 import com.android.server.wm.flicker.dsl.FlickerBuilder
 import com.android.server.wm.flicker.helpers.SeamlessRotationAppHelper
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
 import com.android.server.wm.flicker.testapp.ActivityOptions
 import com.android.server.wm.traces.common.FlickerComponentName
+import org.junit.Assume.assumeFalse
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -100,6 +102,8 @@
     @Presubmit
     @Test
     fun appWindowFullScreen() {
+        // This test doesn't work in shell transitions because of b/206101151
+        assumeFalse(isShellTransitionsEnabled)
         testSpec.assertWm {
             this.invoke("isFullScreen") {
                 val appWindow = it.windowState(testApp.`package`)
@@ -135,6 +139,8 @@
     @Presubmit
     @Test
     fun appLayerAlwaysVisible() {
+        // This test doesn't work in shell transitions because of b/206101151
+        assumeFalse(isShellTransitionsEnabled)
         testSpec.assertLayers {
             isVisible(testApp.component)
         }
@@ -146,6 +152,8 @@
     @Presubmit
     @Test
     fun appLayerRotates() {
+        // This test doesn't work in shell transitions because of b/206101151
+        assumeFalse(isShellTransitionsEnabled)
         testSpec.assertLayers {
             this.invoke("entireScreenCovered") { entry ->
                 entry.entry.displays.map { display ->
@@ -179,6 +187,19 @@
         }
     }
 
+    /**
+     * Checks that the focus doesn't change during animation
+     */
+    @Presubmit
+    @Test
+    fun focusDoesNotChange() {
+        // This test doesn't work in shell transitions because of b/206101151
+        assumeFalse(isShellTransitionsEnabled)
+        testSpec.assertEventLog {
+            this.focusDoesNotChange()
+        }
+    }
+
     /** {@inheritDoc} */
     @FlakyTest
     @Test
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java
index 7ea2a62d..d4bc2a6 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java
@@ -42,7 +42,7 @@
         swView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
         frame.addView(swView);
         final RectsView hwBothView = new RectsView(this, 850, Color.GREEN);
-        // Don't actually need to render to a hw layer, but it's a good sanity-check that
+        // Don't actually need to render to a hw layer, but it's a good check that
         // we're rendering to/from layers correctly
         hwBothView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
         frame.addView(hwBothView);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
index 7173a85..584ab59 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/Lines2Activity.java
@@ -42,7 +42,7 @@
         swView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
         frame.addView(swView);
         final LinesView hwBothView = new LinesView(this, 850, Color.GREEN);
-        // Don't actually need to render to a hw layer, but it's a good sanity-check that
+        // Don't actually need to render to a hw layer, but it's a good check that
         // we're rendering to/from layers correctly
         hwBothView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
         frame.addView(hwBothView);
diff --git a/tests/Internal/src/com/android/internal/util/ParcellingTests.java b/tests/Internal/src/com/android/internal/util/ParcellingTests.java
new file mode 100644
index 0000000..65a3436
--- /dev/null
+++ b/tests/Internal/src/com/android/internal/util/ParcellingTests.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.util;
+
+import android.os.Parcel;
+import android.platform.test.annotations.Presubmit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.Parcelling.BuiltIn.ForInstant;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import java.time.Instant;
+
+/** Tests for {@link Parcelling}. */
+@SmallTest
+@Presubmit
+@RunWith(JUnit4.class)
+public class ParcellingTests {
+
+    private Parcel mParcel = Parcel.obtain();
+
+    @Test
+    public void forInstant_normal() {
+        testForInstant(Instant.ofEpochSecond(500L, 10));
+    }
+
+    @Test
+    public void forInstant_minimum() {
+        testForInstant(Instant.MIN);
+    }
+
+    @Test
+    public void forInstant_maximum() {
+        testForInstant(Instant.MAX);
+    }
+
+    @Test
+    public void forInstant_null() {
+        testForInstant(null);
+    }
+
+    private void testForInstant(Instant instant) {
+        Parcelling<Instant> parcelling = new ForInstant();
+        parcelling.parcel(instant, mParcel, 0);
+        mParcel.setDataPosition(0);
+
+        Instant created = parcelling.unparcel(mParcel);
+
+        if (instant == null) {
+            assertNull(created);
+        } else {
+            assertEquals(instant, created);
+        }
+    }
+
+}
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 e4e535d..da5468e 100644
--- a/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/app/src/com/android/tests/stagedinstallinternal/StagedInstallInternalTest.java
@@ -157,8 +157,18 @@
 
     @Test
     public void testStagedSessionShouldCleanUpOnVerificationFailure() throws Exception {
+        // APEX verification
         InstallUtils.commitExpectingFailure(AssertionError.class, "apexd verification failed",
                 Install.single(APEX_WRONG_SHA_V2).setStaged());
+        InstallUtils.commitExpectingFailure(AssertionError.class, "apexd verification failed",
+                Install.multi(APEX_WRONG_SHA_V2, TestApp.A1).setStaged());
+        // APK verification
+        Install.single(TestApp.A2).commit();
+        assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
+        InstallUtils.commitExpectingFailure(AssertionError.class, "Downgrade detected",
+                Install.single(TestApp.A1).setStaged());
+        InstallUtils.commitExpectingFailure(AssertionError.class, "Downgrade detected",
+                Install.multi(TestApp.A1, TestApp.B1).setStaged());
     }
 
     @Test
@@ -176,6 +186,12 @@
     }
 
     @Test
+    public void testStagedSessionShouldCleanUpOnOnSuccessMultiPackage_Commit() throws Exception {
+        int sessionId = Install.multi(TestApp.A1, TestApp.Apex2).setStaged().commit();
+        storeSessionId(sessionId);
+    }
+
+    @Test
     public void testStagedInstallationShouldCleanUpOnValidationFailure() throws Exception {
         InstallUtils.commitExpectingFailure(AssertionError.class, "INSTALL_FAILED_INVALID_APK",
                 Install.single(TestApp.AIncompleteSplit).setStaged());
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 78cf9ac..926bf1b 100644
--- a/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
+++ b/tests/StagedInstallTest/src/com/android/tests/stagedinstallinternal/host/StagedInstallInternalTest.java
@@ -301,6 +301,18 @@
     }
 
     @Test
+    @LargeTest
+    public void testStagedSessionShouldCleanUpOnOnSuccessMultiPackage() throws Exception {
+        List<String> before = getStagingDirectories();
+        runPhase("testStagedSessionShouldCleanUpOnOnSuccessMultiPackage_Commit");
+        assertThat(getStagingDirectories()).isNotEqualTo(before);
+        getDevice().reboot();
+        runPhase("testStagedSessionShouldCleanUpOnOnSuccess_Verify");
+        List<String> after = getStagingDirectories();
+        assertThat(after).isEqualTo(before);
+    }
+
+    @Test
     public void testStagedInstallationShouldCleanUpOnValidationFailure() throws Exception {
         List<String> before = getStagingDirectories();
         runPhase("testStagedInstallationShouldCleanUpOnValidationFailure");
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 8444833..525a784 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
@@ -207,17 +207,6 @@
             default:
                 device.executeShellCommand("stop");
                 device.executeShellCommand("start");
-                ITestDevice.RecoveryMode cachedRecoveryMode = device.getRecoveryMode();
-                device.setRecoveryMode(ITestDevice.RecoveryMode.ONLINE);
-
-                if (device.isEncryptionSupported()) {
-                    if (device.isDeviceEncrypted()) {
-                        LogUtil.CLog.e("Device is encrypted after userspace reboot!");
-                        device.unlockDevice();
-                    }
-                }
-
-                device.setRecoveryMode(cachedRecoveryMode);
                 device.waitForDeviceAvailable();
                 break;
         }
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
index 937f9dc..15de226 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectedStateTest.java
@@ -119,7 +119,7 @@
     @Test
     public void testNullNetworkDoesNotTriggerDisconnect() throws Exception {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(null);
         mTestLooper.dispatchAll();
 
@@ -131,7 +131,7 @@
     @Test
     public void testNewNetworkTriggersMigration() throws Exception {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_2);
         mTestLooper.dispatchAll();
 
@@ -143,7 +143,7 @@
     @Test
     public void testSameNetworkDoesNotTriggerMigration() throws Exception {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1);
         mTestLooper.dispatchAll();
 
@@ -203,7 +203,7 @@
         triggerChildOpened();
 
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_2);
         getChildSessionCallback()
                 .onIpSecTransformsMigrated(makeDummyIpSecTransform(), makeDummyIpSecTransform());
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java
index d1f3a21..3c70759 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionConnectingStateTest.java
@@ -64,7 +64,7 @@
     @Test
     public void testNullNetworkTriggersDisconnect() throws Exception {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(null);
         mTestLooper.dispatchAll();
 
@@ -76,7 +76,7 @@
     @Test
     public void testNewNetworkTriggersReconnect() throws Exception {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_2);
         mTestLooper.dispatchAll();
 
@@ -89,7 +89,7 @@
     @Test
     public void testSameNetworkDoesNotTriggerReconnect() throws Exception {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1);
         mTestLooper.dispatchAll();
 
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java
index 2056eea..f3eb82f 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionDisconnectedStateTest.java
@@ -78,7 +78,7 @@
     @Test
     public void testNetworkChangesTriggerStateTransitions() throws Exception {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1);
         mTestLooper.dispatchAll();
 
@@ -89,7 +89,7 @@
     @Test
     public void testNullNetworkDoesNotTriggerStateTransition() throws Exception {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(null);
         mTestLooper.dispatchAll();
 
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java
index 1c85979..6568cdd 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionRetryTimeoutStateTest.java
@@ -58,7 +58,7 @@
     @Test
     public void testNewNetworkTriggerRetry() throws Exception {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_2);
         mTestLooper.dispatchAll();
 
@@ -72,7 +72,7 @@
     @Test
     public void testSameNetworkDoesNotTriggerRetry() throws Exception {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1);
         mTestLooper.dispatchAll();
 
@@ -86,7 +86,7 @@
     @Test
     public void testNullNetworkTriggersDisconnect() throws Exception {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(null);
         mTestLooper.dispatchAll();
 
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
index 2b0037e..b9dfda3 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTest.java
@@ -59,7 +59,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
-import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
+import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -238,14 +238,14 @@
     }
 
     @Test
-    public void testSubscriptionSnapshotUpdateNotifiesUnderlyingNetworkTracker() {
+    public void testSubscriptionSnapshotUpdateNotifiesUnderlyingNetworkController() {
         verifyWakeLockSetUp();
 
         final TelephonySubscriptionSnapshot updatedSnapshot =
                 mock(TelephonySubscriptionSnapshot.class);
         mGatewayConnection.updateSubscriptionSnapshot(updatedSnapshot);
 
-        verify(mUnderlyingNetworkTracker).updateSubscriptionSnapshot(eq(updatedSnapshot));
+        verify(mUnderlyingNetworkController).updateSubscriptionSnapshot(eq(updatedSnapshot));
         verifyWakeLockAcquired();
 
         mTestLooper.dispatchAll();
@@ -256,13 +256,13 @@
     @Test
     public void testNonNullUnderlyingNetworkRecordUpdateCancelsAlarm() {
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(null);
 
         verifyDisconnectRequestAlarmAndGetCallback(false /* expectCanceled */);
 
         mGatewayConnection
-                .getUnderlyingNetworkTrackerCallback()
+                .getUnderlyingNetworkControllerCallback()
                 .onSelectedUnderlyingNetworkChanged(TEST_UNDERLYING_NETWORK_RECORD_1);
 
         verify(mDisconnectRequestAlarm).cancel();
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index 64d0bca..8a0af2d 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -16,7 +16,6 @@
 
 package com.android.server.vcn;
 
-import static com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
 import static com.android.server.vcn.VcnGatewayConnection.VcnIkeSession;
 import static com.android.server.vcn.VcnGatewayConnection.VcnNetworkAgent;
 import static com.android.server.vcn.VcnTestUtils.setupIpSecManager;
@@ -62,6 +61,8 @@
 import com.android.server.vcn.Vcn.VcnGatewayStatusCallback;
 import com.android.server.vcn.VcnGatewayConnection.VcnChildSessionCallback;
 import com.android.server.vcn.VcnGatewayConnection.VcnWakeLock;
+import com.android.server.vcn.routeselection.UnderlyingNetworkController;
+import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
 
 import org.junit.Before;
 import org.mockito.ArgumentCaptor;
@@ -137,7 +138,7 @@
     @NonNull protected final VcnGatewayConnectionConfig mConfig;
     @NonNull protected final VcnGatewayStatusCallback mGatewayStatusCallback;
     @NonNull protected final VcnGatewayConnection.Dependencies mDeps;
-    @NonNull protected final UnderlyingNetworkTracker mUnderlyingNetworkTracker;
+    @NonNull protected final UnderlyingNetworkController mUnderlyingNetworkController;
     @NonNull protected final VcnWakeLock mWakeLock;
     @NonNull protected final WakeupMessage mTeardownTimeoutAlarm;
     @NonNull protected final WakeupMessage mDisconnectRequestAlarm;
@@ -158,7 +159,7 @@
         mConfig = VcnGatewayConnectionConfigTest.buildTestConfig();
         mGatewayStatusCallback = mock(VcnGatewayStatusCallback.class);
         mDeps = mock(VcnGatewayConnection.Dependencies.class);
-        mUnderlyingNetworkTracker = mock(UnderlyingNetworkTracker.class);
+        mUnderlyingNetworkController = mock(UnderlyingNetworkController.class);
         mWakeLock = mock(VcnWakeLock.class);
         mTeardownTimeoutAlarm = mock(WakeupMessage.class);
         mDisconnectRequestAlarm = mock(WakeupMessage.class);
@@ -176,9 +177,9 @@
         doReturn(mTestLooper.getLooper()).when(mVcnContext).getLooper();
         doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider();
 
-        doReturn(mUnderlyingNetworkTracker)
+        doReturn(mUnderlyingNetworkController)
                 .when(mDeps)
-                .newUnderlyingNetworkTracker(any(), any(), any(), any());
+                .newUnderlyingNetworkController(any(), any(), any(), any());
         doReturn(mWakeLock)
                 .when(mDeps)
                 .newWakeLock(eq(mContext), eq(PowerManager.PARTIAL_WAKE_LOCK), any());
diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
similarity index 86%
rename from tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
rename to tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
index 5af69b5..c954cb8 100644
--- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/routeselection/UnderlyingNetworkControllerTest.java
@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.server.vcn;
+package com.android.server.vcn.routeselection;
 
 import static com.android.server.vcn.VcnTestUtils.setupSystemService;
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT;
+import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.WIFI_EXIT_RSSI_THRESHOLD_DEFAULT;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
@@ -48,10 +50,11 @@
 import android.util.ArraySet;
 
 import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
-import com.android.server.vcn.UnderlyingNetworkTracker.NetworkBringupCallback;
-import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkListener;
-import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
-import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback;
+import com.android.server.vcn.VcnContext;
+import com.android.server.vcn.VcnNetworkProvider;
+import com.android.server.vcn.routeselection.UnderlyingNetworkController.NetworkBringupCallback;
+import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback;
+import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkListener;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -64,7 +67,7 @@
 import java.util.Set;
 import java.util.UUID;
 
-public class UnderlyingNetworkTrackerTest {
+public class UnderlyingNetworkControllerTest {
     private static final ParcelUuid SUB_GROUP = new ParcelUuid(new UUID(0, 0));
     private static final int INITIAL_SUB_ID_1 = 1;
     private static final int INITIAL_SUB_ID_2 = 2;
@@ -102,14 +105,14 @@
     @Mock private TelephonyManager mTelephonyManager;
     @Mock private CarrierConfigManager mCarrierConfigManager;
     @Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
-    @Mock private UnderlyingNetworkTrackerCallback mNetworkTrackerCb;
+    @Mock private UnderlyingNetworkControllerCallback mNetworkControllerCb;
     @Mock private Network mNetwork;
 
     @Captor private ArgumentCaptor<UnderlyingNetworkListener> mUnderlyingNetworkListenerCaptor;
 
     private TestLooper mTestLooper;
     private VcnContext mVcnContext;
-    private UnderlyingNetworkTracker mUnderlyingNetworkTracker;
+    private UnderlyingNetworkController mUnderlyingNetworkController;
 
     @Before
     public void setUp() {
@@ -140,12 +143,9 @@
 
         when(mSubscriptionSnapshot.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(INITIAL_SUB_IDS);
 
-        mUnderlyingNetworkTracker =
-                new UnderlyingNetworkTracker(
-                        mVcnContext,
-                        SUB_GROUP,
-                        mSubscriptionSnapshot,
-                        mNetworkTrackerCb);
+        mUnderlyingNetworkController =
+                new UnderlyingNetworkController(
+                        mVcnContext, SUB_GROUP, mSubscriptionSnapshot, mNetworkControllerCb);
     }
 
     private void resetVcnContext() {
@@ -181,11 +181,8 @@
                         mVcnNetworkProvider,
                         true /* isInTestMode */);
 
-        new UnderlyingNetworkTracker(
-                vcnContext,
-                SUB_GROUP,
-                mSubscriptionSnapshot,
-                mNetworkTrackerCb);
+        new UnderlyingNetworkController(
+                vcnContext, SUB_GROUP, mSubscriptionSnapshot, mNetworkControllerCb);
 
         verify(cm)
                 .registerNetworkCallback(
@@ -233,7 +230,7 @@
                 mock(TelephonySubscriptionSnapshot.class);
         when(subscriptionUpdate.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(UPDATED_SUB_IDS);
 
-        mUnderlyingNetworkTracker.updateSubscriptionSnapshot(subscriptionUpdate);
+        mUnderlyingNetworkController.updateSubscriptionSnapshot(subscriptionUpdate);
 
         // verify that initially-filed bringup requests are unregistered (cell + wifi)
         verify(mConnectivityManager, times(INITIAL_SUB_IDS.size() + 3))
@@ -255,7 +252,7 @@
         return getExpectedRequestBase()
                 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                 .setSubscriptionIds(netCapsSubIds)
-                .setSignalStrength(UnderlyingNetworkTracker.WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT)
+                .setSignalStrength(WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT)
                 .build();
     }
 
@@ -264,7 +261,7 @@
         return getExpectedRequestBase()
                 .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                 .setSubscriptionIds(netCapsSubIds)
-                .setSignalStrength(UnderlyingNetworkTracker.WIFI_EXIT_RSSI_THRESHOLD_DEFAULT)
+                .setSignalStrength(WIFI_EXIT_RSSI_THRESHOLD_DEFAULT)
                 .build();
     }
 
@@ -304,7 +301,7 @@
 
     @Test
     public void testTeardown() {
-        mUnderlyingNetworkTracker.teardown();
+        mUnderlyingNetworkController.teardown();
 
         // Expect 5 NetworkBringupCallbacks to be unregistered: 1 for WiFi, 2 for Cellular (1x for
         // each subId), and 1 for each of the Wifi signal strength thresholds
@@ -368,7 +365,7 @@
                         networkCapabilities,
                         INITIAL_LINK_PROPERTIES,
                         false /* isBlocked */);
-        verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+        verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
         return cb;
     }
 
@@ -384,7 +381,7 @@
                         UPDATED_NETWORK_CAPABILITIES,
                         INITIAL_LINK_PROPERTIES,
                         false /* isBlocked */);
-        verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+        verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
     }
 
     @Test
@@ -399,7 +396,7 @@
                         INITIAL_NETWORK_CAPABILITIES,
                         UPDATED_LINK_PROPERTIES,
                         false /* isBlocked */);
-        verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+        verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
     }
 
     @Test
@@ -414,11 +411,13 @@
                         SUSPENDED_NETWORK_CAPABILITIES,
                         INITIAL_LINK_PROPERTIES,
                         false /* isBlocked */);
-        verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+        verify(mNetworkControllerCb, times(1))
+                .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
         // onSelectedUnderlyingNetworkChanged() won't be fired twice if network capabilities doesn't
         // change.
         cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES);
-        verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+        verify(mNetworkControllerCb, times(1))
+                .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
     }
 
     @Test
@@ -434,11 +433,13 @@
                         INITIAL_NETWORK_CAPABILITIES,
                         INITIAL_LINK_PROPERTIES,
                         false /* isBlocked */);
-        verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+        verify(mNetworkControllerCb, times(1))
+                .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
         // onSelectedUnderlyingNetworkChanged() won't be fired twice if network capabilities doesn't
         // change.
         cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
-        verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+        verify(mNetworkControllerCb, times(1))
+                .onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
     }
 
     @Test
@@ -453,7 +454,7 @@
                         INITIAL_NETWORK_CAPABILITIES,
                         INITIAL_LINK_PROPERTIES,
                         true /* isBlocked */);
-        verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
+        verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(eq(expectedRecord));
     }
 
     @Test
@@ -462,7 +463,7 @@
 
         cb.onLost(mNetwork);
 
-        verify(mNetworkTrackerCb).onSelectedUnderlyingNetworkChanged(null);
+        verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(null);
     }
 
     @Test
@@ -471,20 +472,20 @@
 
         cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
 
-        // Verify no more calls to the UnderlyingNetworkTrackerCallback when the
+        // Verify no more calls to the UnderlyingNetworkControllerCallback when the
         // UnderlyingNetworkRecord does not actually change
-        verifyNoMoreInteractions(mNetworkTrackerCb);
+        verifyNoMoreInteractions(mNetworkControllerCb);
     }
 
     @Test
     public void testRecordTrackerCallbackNotifiedAfterTeardown() {
         UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
-        mUnderlyingNetworkTracker.teardown();
+        mUnderlyingNetworkController.teardown();
 
         cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES);
 
         // Verify that the only call was during onAvailable()
-        verify(mNetworkTrackerCb, times(1)).onSelectedUnderlyingNetworkChanged(any());
+        verify(mNetworkControllerCb, times(1)).onSelectedUnderlyingNetworkChanged(any());
     }
 
     // TODO (b/187991063): Add tests for network prioritization
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index 740b44e..bd0a4bc 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -170,16 +170,6 @@
 }
 
 // ==========================================================
-// Build the host shared library: aapt2_jni
-// ==========================================================
-cc_library_host_shared {
-    name: "libaapt2_jni",
-    srcs: toolSources + ["jni/aapt2_jni.cpp"],
-    static_libs: ["libaapt2"],
-    defaults: ["aapt2_defaults"],
-}
-
-// ==========================================================
 // Build the host tests: aapt2_tests
 // ==========================================================
 cc_test_host {
diff --git a/tools/aapt2/jni/ScopedUtfChars.h b/tools/aapt2/jni/ScopedUtfChars.h
deleted file mode 100644
index a8c4b13..0000000
--- a/tools/aapt2/jni/ScopedUtfChars.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-#ifndef SCOPED_UTF_CHARS_H_included
-#define SCOPED_UTF_CHARS_H_included
-
-#include <string.h>
-#include <jni.h>
-
-#include "android-base/logging.h"
-
-// This file was copied with some minor modifications from libnativehelper.
-// As soon as libnativehelper can be compiled for Windows, this file should be
-// replaced with libnativehelper's implementation.
-class ScopedUtfChars {
- public:
-  ScopedUtfChars(JNIEnv* env, jstring s) : env_(env), string_(s) {
-    CHECK(s != nullptr);
-    utf_chars_ = env->GetStringUTFChars(s, nullptr);
-  }
-
-  ScopedUtfChars(ScopedUtfChars&& rhs) :
-      env_(rhs.env_), string_(rhs.string_), utf_chars_(rhs.utf_chars_) {
-    rhs.env_ = nullptr;
-    rhs.string_ = nullptr;
-    rhs.utf_chars_ = nullptr;
-  }
-
-  ~ScopedUtfChars() {
-    if (utf_chars_) {
-      env_->ReleaseStringUTFChars(string_, utf_chars_);
-    }
-  }
-
-  ScopedUtfChars& operator=(ScopedUtfChars&& rhs) {
-    if (this != &rhs) {
-      // Delete the currently owned UTF chars.
-      this->~ScopedUtfChars();
-
-      // Move the rhs ScopedUtfChars and zero it out.
-      env_ = rhs.env_;
-      string_ = rhs.string_;
-      utf_chars_ = rhs.utf_chars_;
-      rhs.env_ = nullptr;
-      rhs.string_ = nullptr;
-      rhs.utf_chars_ = nullptr;
-    }
-    return *this;
-  }
-
-  const char* c_str() const {
-    return utf_chars_;
-  }
-
-  size_t size() const {
-    return strlen(utf_chars_);
-  }
-
-  const char& operator[](size_t n) const {
-    return utf_chars_[n];
-  }
-
- private:
-  JNIEnv* env_;
-  jstring string_;
-  const char* utf_chars_;
-
-  DISALLOW_COPY_AND_ASSIGN(ScopedUtfChars);
-};
-
-#endif  // SCOPED_UTF_CHARS_H_included
diff --git a/tools/aapt2/jni/aapt2_jni.cpp b/tools/aapt2/jni/aapt2_jni.cpp
deleted file mode 100644
index ec3c543..0000000
--- a/tools/aapt2/jni/aapt2_jni.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "com_android_tools_aapt2_Aapt2Jni.h"
-
-#include <algorithm>
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "android-base/logging.h"
-#include "ScopedUtfChars.h"
-
-#include "Diagnostics.h"
-#include "cmd/Compile.h"
-#include "cmd/Link.h"
-#include "util/Util.h"
-
-using android::StringPiece;
-
-/*
- * Converts a java List<String> into C++ vector<ScopedUtfChars>.
- */
-static std::vector<ScopedUtfChars> list_to_utfchars(JNIEnv *env, jobject obj) {
-  std::vector<ScopedUtfChars> converted;
-
-  // Call size() method on the list to know how many elements there are.
-  jclass list_cls = env->GetObjectClass(obj);
-  jmethodID size_method_id = env->GetMethodID(list_cls, "size", "()I");
-  CHECK(size_method_id != 0);
-  jint size = env->CallIntMethod(obj, size_method_id);
-  CHECK(size >= 0);
-
-  // Now, iterate all strings in the list
-  // (note: generic erasure means get() return an Object)
-  jmethodID get_method_id = env->GetMethodID(list_cls, "get", "(I)Ljava/lang/Object;");
-  CHECK(get_method_id != 0);
-  for (jint i = 0; i < size; i++) {
-    // Call get(i) to get the string in the ith position.
-    jobject string_obj_uncast = env->CallObjectMethod(obj, get_method_id, i);
-    CHECK(string_obj_uncast != nullptr);
-    jstring string_obj = static_cast<jstring>(string_obj_uncast);
-    converted.push_back(ScopedUtfChars(env, string_obj));
-  }
-
-  return converted;
-}
-
-/*
- * Extracts all StringPiece from the ScopedUtfChars instances.
- *
- * The returned pieces can only be used while the original ones have not been
- * destroyed.
- */
-static std::vector<StringPiece> extract_pieces(const std::vector<ScopedUtfChars> &strings) {
-  std::vector<StringPiece> pieces;
-
-  std::for_each(
-      strings.begin(), strings.end(),
-      [&pieces](const ScopedUtfChars &p) { pieces.push_back(p.c_str()); });
-
-  return pieces;
-}
-
-class JniDiagnostics : public aapt::IDiagnostics {
- public:
-  JniDiagnostics(JNIEnv* env, jobject diagnostics_obj)
-      : env_(env), diagnostics_obj_(diagnostics_obj) {
-    mid_ = NULL;
-  }
-
-  void Log(Level level, aapt::DiagMessageActual& actual_msg) override {
-    jint level_value;
-    switch (level) {
-      case Level::Error:
-        level_value = 3;
-        break;
-
-      case Level::Warn:
-        level_value = 2;
-        break;
-
-      case Level::Note:
-        level_value = 1;
-        break;
-    }
-    jstring message = env_->NewStringUTF(actual_msg.message.c_str());
-    jstring path = env_->NewStringUTF(actual_msg.source.path.c_str());
-    jlong line = -1;
-    if (actual_msg.source.line) {
-      line = actual_msg.source.line.value();
-    }
-    if (!mid_) {
-      jclass diagnostics_cls = env_->GetObjectClass(diagnostics_obj_);
-      mid_ = env_->GetMethodID(diagnostics_cls, "log", "(ILjava/lang/String;JLjava/lang/String;)V");
-    }
-    env_->CallVoidMethod(diagnostics_obj_, mid_, level_value, path, line, message);
-  }
-
- private:
-  JNIEnv* env_;
-  jobject diagnostics_obj_;
-  jmethodID mid_;
-  DISALLOW_COPY_AND_ASSIGN(JniDiagnostics);
-};
-
-JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile(
-    JNIEnv* env, jclass aapt_obj, jobject arguments_obj, jobject diagnostics_obj) {
-  std::vector<ScopedUtfChars> compile_args_jni =
-      list_to_utfchars(env, arguments_obj);
-  std::vector<StringPiece> compile_args = extract_pieces(compile_args_jni);
-  JniDiagnostics diagnostics(env, diagnostics_obj);
-  return aapt::CompileCommand(&diagnostics).Execute(compile_args, &std::cerr);
-}
-
-JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink(JNIEnv* env,
-                                                                        jclass aapt_obj,
-                                                                        jobject arguments_obj,
-                                                                        jobject diagnostics_obj) {
-  std::vector<ScopedUtfChars> link_args_jni =
-      list_to_utfchars(env, arguments_obj);
-  std::vector<StringPiece> link_args = extract_pieces(link_args_jni);
-  JniDiagnostics diagnostics(env, diagnostics_obj);
-  return aapt::LinkCommand(&diagnostics).Execute(link_args, &std::cerr);
-}
-
-JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_ping(
-        JNIEnv *env, jclass aapt_obj) {
-  // This is just a no-op method to see if the library has been loaded.
-}
diff --git a/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h b/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h
deleted file mode 100644
index 3cd9865..0000000
--- a/tools/aapt2/jni/com_android_tools_aapt2_Aapt2Jni.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* DO NOT EDIT THIS FILE - it is machine generated */
-#include <jni.h>
-/* Header for class com_android_tools_aapt2_Aapt2Jni */
-
-#ifndef _Included_com_android_tools_aapt2_Aapt2Jni
-#define _Included_com_android_tools_aapt2_Aapt2Jni
-#ifdef __cplusplus
-extern "C" {
-#endif
-/*
- * Class:     com_android_tools_aapt2_Aapt2Jni
- * Method:    ping
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_com_android_tools_aapt2_Aapt2Jni_ping
-  (JNIEnv *, jclass);
-
-/*
- * Class:     com_android_tools_aapt2_Aapt2Jni
- * Method:    nativeCompile
- * Signature: (Ljava/util/List;Lcom/android/tools/aapt2/Aapt2JniDiagnostics;)I
- */
-JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeCompile(JNIEnv*, jclass, jobject,
-                                                                           jobject);
-
-/*
- * Class:     com_android_tools_aapt2_Aapt2Jni
- * Method:    nativeLink
- * Signature: (Ljava/util/List;Lcom/android/tools/aapt2/Aapt2JniDiagnostics;)I
- */
-JNIEXPORT jint JNICALL Java_com_android_tools_aapt2_Aapt2Jni_nativeLink(JNIEnv*, jclass, jobject,
-                                                                        jobject);
-
-#ifdef __cplusplus
-}
-#endif
-#endif
diff --git a/tools/aosp/aosp_sha.sh b/tools/aosp/aosp_sha.sh
index ac23c3d..36bea57 100755
--- a/tools/aosp/aosp_sha.sh
+++ b/tools/aosp/aosp_sha.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 LOCAL_DIR="$( dirname "${BASH_SOURCE}" )"
 
-if git branch -vv | grep -q -P "^\*[^\[]+\[aosp/"; then
+if git branch -vv | grep -q -E "^\*[^\[]+\[aosp/"; then
     # Change appears to be in AOSP
     exit 0
 elif git log -n 1 --format='%B' $1 | grep -q -E "^Ignore-AOSP-First: .+" ; then